From 235cb4a7ee982c63e403ff28c54a8df38c6f9666 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Fri, 25 Oct 2024 17:22:43 +0100 Subject: [PATCH 01/45] Move doc generation to own pipeline task --- build.yaml | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/build.yaml b/build.yaml index ec0a5ed7..301f621d 100644 --- a/build.yaml +++ b/build.yaml @@ -35,6 +35,13 @@ BuildWorkflow: - Build_Module_ModuleBuilder - Build_NestedModules_ModuleBuilder - Create_changelog_release_output + + pack: + - build + - docs + - package_module_nupkg + + docs: - Generate_Conceptual_Help - Generate_Wiki_Content - Generate_Markdown_For_Public_Commands @@ -43,10 +50,6 @@ BuildWorkflow: - Clean_Markdown_Of_Public_Commands - Clean_Markdown_Metadata - pack: - - build - - package_module_nupkg - hqrmtest: - DscResource_Tests_Stop_On_Fail @@ -138,16 +141,6 @@ DscResource.DocGenerator: - '\*(.+?)\*' # Match Italic (asterisk) Publish_GitHub_Wiki_Content: Debug: true - Generate_Wiki_Content: - MofResourceMetadata: - Type: MofResource - Category: Resources - ClassResourceMetadata: - Type: ClassResource - Category: Resources - CompositeResourceMetadata: - Type: CompositeResource - Category: Resources Generate_Wiki_Sidebar: - Debug: false - AlwaysOverwrite: true + Debug: false + AlwaysOverwrite: true From 145469cd1328ab6ea8904d94ceae0d13210b8275 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Fri, 25 Oct 2024 17:23:12 +0100 Subject: [PATCH 02/45] Fix DscClass Doc Generation --- .../Get-ClassPropertyCustomAttribute.ps1 | 16 ++ .../Private/Get-ClassResourcePropertyNew.ps1 | 165 ++++++++++++++++++ .../Get-ClassResourcePropertyState2.ps1 | 76 ++++++++ source/Private/Get-DscPropertyType.ps1 | 31 ++++ .../Get-DscResourceSchemaPropertyContent.ps1 | 15 +- .../Private/New-DscClassResourceWikiPage.ps1 | 32 ++-- ...Test-ClassPropertyDscAttributeArgument.ps1 | 102 +++++++++++ 7 files changed, 420 insertions(+), 17 deletions(-) create mode 100644 source/Private/Get-ClassPropertyCustomAttribute.ps1 create mode 100644 source/Private/Get-ClassResourcePropertyNew.ps1 create mode 100644 source/Private/Get-ClassResourcePropertyState2.ps1 create mode 100644 source/Private/Get-DscPropertyType.ps1 create mode 100644 source/Private/Test-ClassPropertyDscAttributeArgument.ps1 diff --git a/source/Private/Get-ClassPropertyCustomAttribute.ps1 b/source/Private/Get-ClassPropertyCustomAttribute.ps1 new file mode 100644 index 00000000..402381f2 --- /dev/null +++ b/source/Private/Get-ClassPropertyCustomAttribute.ps1 @@ -0,0 +1,16 @@ +function Get-ClassPropertyCustomAttribute { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [System.Reflection.CustomAttributeData[]] + $Attributes, + + [Parameter(Mandatory = $true)] + [System.String] + $AttributeType + ) + + process { + return $Attributes | Where-Object {$_.AttributeType.Name -eq $AttributeType} + } +} diff --git a/source/Private/Get-ClassResourcePropertyNew.ps1 b/source/Private/Get-ClassResourcePropertyNew.ps1 new file mode 100644 index 00000000..70a1027c --- /dev/null +++ b/source/Private/Get-ClassResourcePropertyNew.ps1 @@ -0,0 +1,165 @@ +<# + .SYNOPSIS + Returns DSC class resource properties from the provided class or classes. + + .DESCRIPTION + Returns DSC class resource properties from the provided class or classes. + + .PARAMETER SourcePath + The path to the source folder (in which the child folder 'Classes' exist). + + .PARAMETER BuiltModuleScriptFilePath + The path to the built module script file that contains the class. + + .PARAMETER ClassName + One or more class names to return properties for. + + .EXAMPLE + Get-ClassResourceProperty -ClassName @('myParentClass', 'myClass') -BuiltModuleScriptFilePath '.\output\MyModule\1.0.0\MyModule.psm1' -SourcePath '.\source' + + Returns all DSC class resource properties. +#> +function Get-ClassResourcePropertyNew +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable[]])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $SourcePath, + + # [Parameter(Mandatory = $true)] + # [System.String] + # $BuiltModuleScriptFilePath, + + [Parameter(Mandatory = $true)] + [System.Reflection.PropertyInfo[]] + $Properties + + + ) + + $resourceProperty = [System.Collections.Hashtable[]] @() + + $className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name + + foreach ($currentClassName in $className) + { + #$dscResourceAst = Get-ClassAst -ClassName $currentClassName -ScriptFile $BuiltModuleScriptFilePath + + $classExists = $false + $sourceFilePath = '' + $childPaths = @( + ('Classes/???.{0}.ps1' -f $currentClassName) + ('Classes/{0}.ps1' -f $currentClassName) + ) + + foreach ($childPath in $childPaths) + { + $sourceFilePath = Join-Path -Path $SourcePath -ChildPath $childPath + + if ((Test-Path -Path $sourceFilePath)) + { + $classExists = $true + break + } + } + + <# + Skip if the class's source file does not exist. This can happen if the + class uses a parent class from a different module. + #> + if (-not $classExists) + { + continue + } + + $dscResourceCommentBasedHelp = Get-CommentBasedHelp -Path $sourceFilePath + + # $astFilter = { + # $args[0] -is [System.Management.Automation.Language.PropertyMemberAst] ` + # -and $args[0].Attributes.TypeName.Name -eq 'DscProperty' + # } + + # $propertyMemberAsts = $dscResourceAst.FindAll($astFilter, $true) + $propertyMembers = $Properties | Where-Object { $_.DeclaringType.Name -eq $currentClassName } + + <# + Looping through each resource property to build the resulting + hashtable. Hashtable will be in the format: + + @{ + Name = + State = 'Key' | 'Required' |'Write' | 'Read' + Description = + EmbeddedInstance = 'MSFT_Credential' | $null + DataType = 'System.String' | 'System.String[] | etc. + IsArray = $true | $false + ValueMap = @( | ...) + } + #> + foreach ($propertyMember in $propertyMembers) + { + Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMember.Name, $currentClassName) + + $propertyAttribute = @{ + Name = $propertyMember.Name + DataType = Get-DscPropertyType -PropertyType $propertyMember.PropertyType + + # Always set to null, correct type name is set in DataType. + EmbeddedInstance = $null + + # Always set to $false - correct type name is set in DataType. + IsArray = $false + } + + $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember + + $valueMapValues = $null + if ($propertyMember.PropertyType.IsEnum) + { + $valueMapValues = $propertyMember.PropertyType.GetEnumNames() + } + + $validateSet = Get-ClassPropertyCustomAttribute -Attributes $propertyMember.CustomAttributes -AttributeType 'ValidateSetAttribute' + if ($validateSet) + { + $valueMapValues = $validateSet.ConstructorArguments.Value.Value + } + + if ($valueMapValues) + { + $propertyAttribute.ValueMap = $valueMapValues + } + + if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0) + { + # The key name must be upper-case for it to match the right item in the list of parameters. + $propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMember.Name.ToUpper()] + + if ($propertyDescription) + { + $propertyDescription = Format-Text -Text $propertyDescription -Format @( + 'Remove_Blank_Rows_At_End_Of_String', + 'Remove_Indentation_From_Blank_Rows', + 'Replace_NewLine_With_One_Whitespace', + 'Replace_Vertical_Bar_With_One_Whitespace', + 'Replace_Multiple_Whitespace_With_One', + 'Remove_Whitespace_From_End_Of_String' + ) + } + } + else + { + $propertyDescription = '' + } + + $propertyAttribute.Description = $propertyDescription + + $resourceProperty += $propertyAttribute + } + } + + return $resourceProperty +} diff --git a/source/Private/Get-ClassResourcePropertyState2.ps1 b/source/Private/Get-ClassResourcePropertyState2.ps1 new file mode 100644 index 00000000..81a88273 --- /dev/null +++ b/source/Private/Get-ClassResourcePropertyState2.ps1 @@ -0,0 +1,76 @@ +<# + .SYNOPSIS + This function returns the property state value of an class-based DSC + resource property. + + .DESCRIPTION + This function returns the property state value of an DSC class-based + resource property. + + .PARAMETER Ast + The Abstract Syntax Tree (AST) for class-based DSC resource property. + The passed value must be an AST of the type 'PropertyMemberAst'. + + .EXAMPLE + Get-ClassResourcePropertyState -Ast { + [DscResource()] + class NameOfResource { + [DscProperty(Key)] + [string] $KeyName + + [NameOfResource] Get() { + return $this + } + + [void] Set() {} + + [bool] Test() { + return $true + } + } + }.Ast.Find({$args[0] -is [System.Management.Automation.Language.PropertyMemberAst]}, $false) + + Returns the property state for the property 'KeyName'. +#> +function Get-ClassResourcePropertyState2 +{ + [CmdletBinding()] + [OutputType([System.String])] + param + ( + [Parameter(Mandatory = $true)] + [System.Reflection.PropertyInfo] + $PropertyInfo + ) + + <# + Check for Key first since it it possible to use both Key and Mandatory + on a property and in that case we want to return just 'Key'. + #> + # Data lives in $PropertyInfo.CustomProperties.NamedArguments + # Need to check attribute type is correct + # TODO: Need to deal with Attribute = False?? + + $attributeParams = @{ + PropertyAttributes = $PropertyInfo.CustomAttributes + } + + if ((Test-ClassPropertyDscAttributeArgument -IsKey @attributeParams)) + { + $propertyState = 'Key' + } + elseif ((Test-ClassPropertyDscAttributeArgument -IsMandatory @attributeParams)) + { + $propertyState = 'Required' + } + elseif ((Test-ClassPropertyDscAttributeArgument -IsRead @attributeParams)) + { + $propertyState = 'Read' + } + elseif ((Test-ClassPropertyDscAttributeArgument -IsWrite @attributeParams)) + { + $propertyState = 'Write' + } + + return $propertyState +} diff --git a/source/Private/Get-DscPropertyType.ps1 b/source/Private/Get-DscPropertyType.ps1 new file mode 100644 index 00000000..e1f7b50e --- /dev/null +++ b/source/Private/Get-DscPropertyType.ps1 @@ -0,0 +1,31 @@ + + +# takes a System.RuntimeType - a System.Reflection.PropertyInfo .PropertyType + +# Check PropertyType.Name = 'Nullable`1' +# Get value from GenericTypeArgument.FullName + +# else return FullName + +function Get-DscPropertyType +{ + [CmdletBinding()] + [OutputType([System.String])] + param ( + [Parameter(Mandatory = $true)] + [System.Type] + $PropertyType + ) + + switch ($PropertyType.Name) + { + 'Nullable`1' + { + return $PropertyType.GenericTypeArguments.Name + } + Default + { + return $PropertyType.Name + } + } +} diff --git a/source/Private/Get-DscResourceSchemaPropertyContent.ps1 b/source/Private/Get-DscResourceSchemaPropertyContent.ps1 index ac194d0c..1650b4e3 100644 --- a/source/Private/Get-DscResourceSchemaPropertyContent.ps1 +++ b/source/Private/Get-DscResourceSchemaPropertyContent.ps1 @@ -50,7 +50,20 @@ function Get-DscResourceSchemaPropertyContent $stringArray += '| Parameter | Attribute | DataType | Description | Allowed Values |' $stringArray += '| --- | --- | --- | --- | --- |' - foreach ($currentProperty in $Property) + # Order the properties + $orderedProperties = @() + $sortOrder = @( + 'Key' + 'Required' + 'Write' + 'Read' + ) + + foreach ($key in $sortOrder) { + $orderedProperties += $Property.GetEnumerator() | Where-Object {$_.State -eq $key} | Sort-Object {$_.Name} + } + + foreach ($currentProperty in $orderedProperties) { if ($currentProperty.EmbeddedInstance -eq 'MSFT_Credential') { diff --git a/source/Private/New-DscClassResourceWikiPage.ps1 b/source/Private/New-DscClassResourceWikiPage.ps1 index eb9c697a..922e3752 100644 --- a/source/Private/New-DscClassResourceWikiPage.ps1 +++ b/source/Private/New-DscClassResourceWikiPage.ps1 @@ -92,14 +92,18 @@ function New-DscClassResourceWikiPage # Looping through each module file (normally just one). foreach ($builtModuleScriptFile in $builtModuleScriptFiles) { - $dscResourceAsts = Get-ClassResourceAst -ScriptFile $builtModuleScriptFile.FullName + Import-Module $builtModuleScriptFile.FullName - Write-Verbose -Message ($script:localizedData.FoundClassBasedMessage -f $dscResourceAsts.Count, $builtModuleScriptFile.FullName) + $classesInModule = (Get-Module $builtModuleScriptFile.BaseName).ImplementingAssembly.DefinedTypes | Where-Object { $_.IsClass -and $_.IsPublic } + $dscClassesInModule = $classesInModule | Where-Object {'DscResourceAttribute' -in $_.CustomAttributes.AttributeType.Name} + + Write-Verbose -Message ($script:localizedData.FoundClassBasedMessage -f $dscClassesInModule.Count, $builtModuleScriptFile.FullName) # Looping through each class-based resource. - foreach ($dscResourceAst in $dscResourceAsts) + # TODO: Should this include non Dsc Classes? + foreach ($dscClassInModule in $dscClassesInModule) { - Write-Verbose -Message ($script:localizedData.GenerateWikiPageMessage -f $dscResourceAst.Name) + Write-Verbose -Message ($script:localizedData.GenerateWikiPageMessage -f $dscClassInModule.Name) $output = New-Object -TypeName 'System.Text.StringBuilder' @@ -118,24 +122,20 @@ function New-DscClassResourceWikiPage } # Add the documentation for the resource. - $null = $output.AppendLine("# $($dscResourceAst.Name)") + $null = $output.AppendLine("# $($dscClassInModule.Name)") $null = $output.AppendLine() $null = $output.AppendLine('## Parameters') $null = $output.AppendLine() - $sourceFilePath = Join-Path -Path $SourcePath -ChildPath ('Classes/*{0}.ps1' -f $dscResourceAst.Name) - - $className = @() + $sourceFilePath = Join-Path -Path $SourcePath -ChildPath ('Classes/*{0}.ps1' -f $dscClassInModule.Name) - if ($dscResourceAst.BaseTypes.Count -gt 0) - { - $className += @($dscResourceAst.BaseTypes.TypeName.Name) - } + $dscProperties = $dscClassInModule.GetProperties() | Where-Object {'DscPropertyAttribute' -in $_.CustomAttributes.AttributeType.Name} - $className += $dscResourceAst.Name + #$className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name # Returns the properties for class and any existing parent class(es). - $resourceProperty = Get-ClassResourceProperty -ClassName $className -SourcePath $SourcePath -BuiltModuleScriptFilePath $builtModuleScriptFile.FullName + $resourceProperty = Get-ClassResourcePropertyNew -Properties $dscProperties -SourcePath $SourcePath + #$resourceProperty = Get-ClassResourcePropertyNew -ClassName $className -SourcePath $SourcePath -BuiltModuleScriptFilePath $builtModuleScriptFile.FullName $propertyContent = Get-DscResourceSchemaPropertyContent -Property $resourceProperty -UseMarkdown @@ -156,7 +156,7 @@ function New-DscClassResourceWikiPage $null = $output.AppendLine($description) $null = $output.AppendLine() - $examplesPath = Join-Path -Path $SourcePath -ChildPath ('Examples\Resources\{0}' -f $dscResourceAst.Name) + $examplesPath = Join-Path -Path $SourcePath -ChildPath ('Examples\Resources\{0}' -f $dscClassInModule.Name) $examplesOutput = Get-ResourceExampleAsMarkdown -Path $examplesPath @@ -165,7 +165,7 @@ function New-DscClassResourceWikiPage $null = $output.Append($examplesOutput) } - $outputFileName = '{0}.md' -f $dscResourceAst.Name + $outputFileName = '{0}.md' -f $dscClassInModule.Name $savePath = Join-Path -Path $OutputPath -ChildPath $outputFileName diff --git a/source/Private/Test-ClassPropertyDscAttributeArgument.ps1 b/source/Private/Test-ClassPropertyDscAttributeArgument.ps1 new file mode 100644 index 00000000..27e3d175 --- /dev/null +++ b/source/Private/Test-ClassPropertyDscAttributeArgument.ps1 @@ -0,0 +1,102 @@ +<# + .SYNOPSIS + This function returns the property state value of an class-based DSC + resource property. + + .DESCRIPTION + This function returns the property state value of an DSC class-based + resource property. + + .PARAMETER Ast + The Abstract Syntax Tree (AST) for class-based DSC resource property. + The passed value must be an AST of the type 'PropertyMemberAst'. + + .PARAMETER IsKey + Specifies if the parameter is expected to have the type qualifier Key. + + .PARAMETER IsMandatory + Specifies if the parameter is expected to have the type qualifier Mandatory. + + .PARAMETER IsWrite + Specifies if the parameter is expected to have the type qualifier Write. + + .PARAMETER IsRead + Specifies if the parameter is expected to have the type qualifier Read. + + .EXAMPLE + Test-PropertyMemberAst -IsKey -Ast { + [DscResource()] + class NameOfResource { + [DscProperty(Key)] + [string] $KeyName + + [NameOfResource] Get() { + return $this + } + + [void] Set() {} + + [bool] Test() { + return $true + } + } + }.Ast.Find({$args[0] -is [System.Management.Automation.Language.PropertyMemberAst]}, $false) + + Returns $true that the property 'KeyName' is Key. +#> + +# From provided CustomAttribute +# Return desired Dsc value if true e.g. Key|Mandatory|Read|Write + +function Test-ClassPropertyDscAttributeArgument +{ + [CmdletBinding()] + [OutputType([System.Boolean])] + param + ( + [Parameter(Mandatory = $true)] + [System.Reflection.CustomAttributeData[]] + $PropertyAttributes, + + [Parameter(Mandatory = $true, ParameterSetName = 'IsKey')] + [System.Management.Automation.SwitchParameter] + $IsKey, + + [Parameter(Mandatory = $true, ParameterSetName = 'IsMandatory')] + [System.Management.Automation.SwitchParameter] + $IsMandatory, + + [Parameter(Mandatory = $true, ParameterSetName = 'IsWrite')] + [System.Management.Automation.SwitchParameter] + $IsWrite, + + [Parameter(Mandatory = $true, ParameterSetName = 'IsRead')] + [System.Management.Automation.SwitchParameter] + $IsRead + ) + + $attributes = Get-ClassPropertyCustomAttribute -Attributes $PropertyAttributes -AttributeType 'DscPropertyAttribute' + + if ($IsKey.IsPresent -and 'Key' -in $attributes.NamedArguments.MemberName) + { + return $true + } + + # Having Key on a property makes it implicitly Mandatory. + if ($IsMandatory.IsPresent -and $attributes.NamedArguments.MemberName -in @('Mandatory', 'Key')) + { + return $true + } + + if ($IsRead.IsPresent -and 'NotConfigurable' -in $attributes.NamedArguments.MemberName) + { + return $true + } + + if ($IsWrite.IsPresent -and $attributes.NamedArguments.MemberName -notin @('Key', 'Mandatory', 'NotConfigurable')) + { + return $true + } + + return $false +} From 4b57710de6c1113edf39bb68f529e239ba7c6e8d Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Fri, 25 Oct 2024 17:32:45 +0100 Subject: [PATCH 03/45] Remove unused files --- source/Private/Get-ClassAst.ps1 | 69 -- source/Private/Get-ClassResourceAst.ps1 | 65 -- source/Private/Get-ClassResourceProperty.ps1 | 155 ----- tests/unit/private/Get-ClassAst.Tests.ps1 | 120 ---- .../private/Get-ClassResourceAst.Tests.ps1 | 99 --- .../Get-ClassResourceProperty.Tests.ps1 | 591 ------------------ 6 files changed, 1099 deletions(-) delete mode 100644 source/Private/Get-ClassAst.ps1 delete mode 100644 source/Private/Get-ClassResourceAst.ps1 delete mode 100644 source/Private/Get-ClassResourceProperty.ps1 delete mode 100644 tests/unit/private/Get-ClassAst.Tests.ps1 delete mode 100644 tests/unit/private/Get-ClassResourceAst.Tests.ps1 delete mode 100644 tests/unit/private/Get-ClassResourceProperty.Tests.ps1 diff --git a/source/Private/Get-ClassAst.ps1 b/source/Private/Get-ClassAst.ps1 deleted file mode 100644 index d79ffc5e..00000000 --- a/source/Private/Get-ClassAst.ps1 +++ /dev/null @@ -1,69 +0,0 @@ -<# - .SYNOPSIS - Returns the AST for a single or all classes. - - .DESCRIPTION - Returns the AST for a single or all classes. - - .PARAMETER ScriptFile - The path to the source file that contain the class. - - .PARAMETER ClassName - The specific class to return the AST for. Optional. - - .EXAMPLE - Get-ClassAst -ScriptFile '.\output\MyModule\1.0.0\MyModule.psm1' - - Returns AST for all the classes in the script file. - - .EXAMPLE - Get-ClassAst -ClassName 'myClass' -ScriptFile '.\output\MyModule\1.0.0\MyModule.psm1' - - Returns AST for the class 'myClass' from the script file. -#> -function Get-ClassAst -{ - [CmdletBinding()] - [OutputType([System.Collections.Generic.IEnumerable`1[System.Management.Automation.Language.Ast]])] - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $ScriptFile, - - [Parameter()] - [System.String] - $ClassName - ) - - $tokens, $parseErrors = $null - - $ast = [System.Management.Automation.Language.Parser]::ParseFile($ScriptFile, [ref] $tokens, [ref] $parseErrors) - - if ($parseErrors) - { - throw $parseErrors - } - - if ($PSBoundParameters.ContainsKey('ClassName') -and $ClassName) - { - # Get only the specific class resource. - $astFilter = { - $args[0] -is [System.Management.Automation.Language.TypeDefinitionAst] ` - -and $args[0].IsClass ` - -and $args[0].Name -eq $ClassName - } - } - else - { - # Get all class resources. - $astFilter = { - $args[0] -is [System.Management.Automation.Language.TypeDefinitionAst] ` - -and $args[0].IsClass - } - } - - $classAst = $ast.FindAll($astFilter, $true) - - return $classAst -} diff --git a/source/Private/Get-ClassResourceAst.ps1 b/source/Private/Get-ClassResourceAst.ps1 deleted file mode 100644 index cc9c25e6..00000000 --- a/source/Private/Get-ClassResourceAst.ps1 +++ /dev/null @@ -1,65 +0,0 @@ -<# - .SYNOPSIS - Returns the AST for a single or all DSC class resources. - - .DESCRIPTION - Returns the AST for a single or all DSC class resources. - - .PARAMETER ScriptFile - The path to the source file that contain the DSC class resource. - - .PARAMETER ClassName - The specific DSC class resource to return the AST for. Optional. - - .EXAMPLE - Get-ClassResourceAst -ClassName 'myClass' -ScriptFile '.\output\MyModule\1.0.0\MyModule.psm1' - - Returns AST for all DSC class resources in the script file. - - .EXAMPLE - Get-ClassResourceAst -ClassName 'myClass' -ScriptFile '.\output\MyModule\1.0.0\MyModule.psm1' - - Returns AST for the DSC class resource 'myClass' from the script file. -#> -function Get-ClassResourceAst -{ - [CmdletBinding()] - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $ScriptFile, - - [Parameter()] - [System.String] - $ClassName - ) - - $dscClassResourceAst = $null - - $getClassAstParameters = @{ - ScriptFile = $ScriptFile - } - - if ($PSBoundParameters.ContainsKey('ClassName')) - { - $getClassAstParameters['ClassName'] = $ClassName - } - - $ast = Get-ClassAst @getClassAstParameters - - # Only try to filter if there was at least one class returned. - if ($ast) - { - # Get only DSC class resource. - $astFilter = { - $args[0] -is [System.Management.Automation.Language.TypeDefinitionAst] ` - -and $args[0].IsClass ` - -and $args[0].Attributes.Extent.Text -imatch '\[DscResource\(.*\)\]' - } - - $dscClassResourceAst = $ast.FindAll($astFilter, $true) - } - - return $dscClassResourceAst -} diff --git a/source/Private/Get-ClassResourceProperty.ps1 b/source/Private/Get-ClassResourceProperty.ps1 deleted file mode 100644 index 589fb7ec..00000000 --- a/source/Private/Get-ClassResourceProperty.ps1 +++ /dev/null @@ -1,155 +0,0 @@ -<# - .SYNOPSIS - Returns DSC class resource properties from the provided class or classes. - - .DESCRIPTION - Returns DSC class resource properties from the provided class or classes. - - .PARAMETER SourcePath - The path to the source folder (in which the child folder 'Classes' exist). - - .PARAMETER BuiltModuleScriptFilePath - The path to the built module script file that contains the class. - - .PARAMETER ClassName - One or more class names to return properties for. - - .EXAMPLE - Get-ClassResourceProperty -ClassName @('myParentClass', 'myClass') -BuiltModuleScriptFilePath '.\output\MyModule\1.0.0\MyModule.psm1' -SourcePath '.\source' - - Returns all DSC class resource properties. -#> -function Get-ClassResourceProperty -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable[]])] - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $SourcePath, - - [Parameter(Mandatory = $true)] - [System.String] - $BuiltModuleScriptFilePath, - - [Parameter(Mandatory = $true)] - [System.String[]] - $ClassName - ) - - $resourceProperty = [System.Collections.Hashtable[]] @() - - foreach ($currentClassName in $ClassName) - { - $dscResourceAst = Get-ClassAst -ClassName $currentClassName -ScriptFile $BuiltModuleScriptFilePath - - $classExists = $false - $sourceFilePath = '' - $childPaths = @( - ('Classes/???.{0}.ps1' -f $currentClassName) - ('Classes/{0}.ps1' -f $currentClassName) - ) - - foreach ($childPath in $childPaths) - { - $sourceFilePath = Join-Path -Path $SourcePath -ChildPath $childPath - - if ((Test-Path -Path $sourceFilePath)) - { - $classExists = $true - break - } - } - - <# - Skip if the class's source file does not exist. This can happen if the - class uses a parent class from a different module. - #> - if (-not $classExists) - { - continue - } - - $dscResourceCommentBasedHelp = Get-CommentBasedHelp -Path $sourceFilePath - - $astFilter = { - $args[0] -is [System.Management.Automation.Language.PropertyMemberAst] ` - -and $args[0].Attributes.TypeName.Name -eq 'DscProperty' - } - - $propertyMemberAsts = $dscResourceAst.FindAll($astFilter, $true) - - <# - Looping through each resource property to build the resulting - hashtable. Hashtable will be in the format: - - @{ - Name = - State = 'Key' | 'Required' |'Write' | 'Read' - Description = - EmbeddedInstance = 'MSFT_Credential' | $null - DataType = 'System.String' | 'System.String[] | etc. - IsArray = $true | $false - ValueMap = @( | ...) - } - #> - foreach ($propertyMemberAst in $propertyMemberAsts) - { - Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMemberAst.Name, $dscResourceAst.Name) - - $propertyAttribute = @{ - Name = $propertyMemberAst.Name - DataType = $propertyMemberAst.PropertyType.TypeName.FullName - - # Always set to null, correct type name is set in DataType. - EmbeddedInstance = $null - - # Always set to $false - correct type name is set in DataType. - IsArray = $false - } - - $propertyAttribute['State'] = Get-ClassResourcePropertyState -Ast $propertyMemberAst - - $astFilter = { - $args[0] -is [System.Management.Automation.Language.AttributeAst] ` - -and $args[0].TypeName.Name -eq 'ValidateSet' - } - - $propertyAttributeAsts = $propertyMemberAst.FindAll($astFilter, $true) - - if ($propertyAttributeAsts) - { - $propertyAttribute['ValueMap'] = $propertyAttributeAsts.PositionalArguments.Value - } - - if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0) - { - # The key name must be upper-case for it to match the right item in the list of parameters. - $propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMemberAst.Name.ToUpper()] - - if ($propertyDescription) - { - $propertyDescription = Format-Text -Text $propertyDescription -Format @( - 'Remove_Blank_Rows_At_End_Of_String', - 'Remove_Indentation_From_Blank_Rows', - 'Replace_NewLine_With_One_Whitespace', - 'Replace_Vertical_Bar_With_One_Whitespace', - 'Replace_Multiple_Whitespace_With_One', - 'Remove_Whitespace_From_End_Of_String' - ) - } - } - else - { - $propertyDescription = '' - } - - $propertyAttribute['Description'] = $propertyDescription - - $resourceProperty += $propertyAttribute - } - } - - return $resourceProperty -} diff --git a/tests/unit/private/Get-ClassAst.Tests.ps1 b/tests/unit/private/Get-ClassAst.Tests.ps1 deleted file mode 100644 index 388fbfb3..00000000 --- a/tests/unit/private/Get-ClassAst.Tests.ps1 +++ /dev/null @@ -1,120 +0,0 @@ -#region HEADER -$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path -$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { - ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and - $(try - { - Test-ModuleManifest -Path $_.FullName -ErrorAction Stop - } - catch - { - $false - }) - }).BaseName - -$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 -Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' - -Import-Module $script:moduleName -Force -ErrorAction 'Stop' -#endregion HEADER - -InModuleScope $script:moduleName { - Describe 'Get-ClassAst' { - Context 'When the script file cannot be parsed' { - BeforeAll { - $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' - - New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force - - $mockBuiltModuleScriptFilePath = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' - - # The class DSC resource in the built module. - $mockBuiltModuleScript = @' -[DscResource()] -class MyDscResource -{ - [MyDscResource] Get() - { - return [MyDscResource] $this - } - - [System.Boolean] Test() - { - return $true - } - - [DscProperty(Key)] - [System.String] $ProjectName -} -'@ - - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath $mockBuiltModuleScriptFilePath -Encoding ascii -Force - } - - It 'Should throw an error' { - # This evaluates just part of the expected error message. - { Get-ClassAst -ScriptFile $mockBuiltModuleScriptFilePath } | Should -Throw "'MyDscResource' is missing a Set method" - } - } - - Context 'When the script file is parsed successfully' { - BeforeAll { - $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' - - New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force - - $mockBuiltModuleScriptFilePath = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' - - # The class DSC resource in the built module. - $mockBuiltModuleScript = @' -class MyBaseClass -{ - [void] MyHelperFunction() {} -} - -[DscResource()] -class MyDscResource -{ - [MyDscResource] Get() - { - return [MyDscResource] $this - } - - [System.Boolean] Test() - { - return $true - } - - [void] Set() {} - - [DscProperty(Key)] - [System.String] $ProjectName -} -'@ - - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath $mockBuiltModuleScriptFilePath -Encoding ascii -Force - } - - Context 'When returning all classes in the script file' { - It 'Should return the correct classes' { - $astResult = Get-ClassAst -ScriptFile $mockBuiltModuleScriptFilePath - - $astResult | Should -HaveCount 2 - $astResult.Name | Should -Contain 'MyDscResource' - $astResult.Name | Should -Contain 'MyBaseClass' - } - } - - Context 'When returning a single class from the script file' { - It 'Should return the correct classes' { - $astResult = Get-ClassAst -ScriptFile $mockBuiltModuleScriptFilePath -ClassName 'MyBaseClass' - - $astResult | Should -HaveCount 1 - $astResult.Name | Should -Be 'MyBaseClass' - } - } - } - } -} diff --git a/tests/unit/private/Get-ClassResourceAst.Tests.ps1 b/tests/unit/private/Get-ClassResourceAst.Tests.ps1 deleted file mode 100644 index 4620951a..00000000 --- a/tests/unit/private/Get-ClassResourceAst.Tests.ps1 +++ /dev/null @@ -1,99 +0,0 @@ -#region HEADER -$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path -$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { - ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and - $(try - { - Test-ModuleManifest -Path $_.FullName -ErrorAction Stop - } - catch - { - $false - }) - }).BaseName - -$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 -Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' - -Import-Module $script:moduleName -Force -ErrorAction 'Stop' -#endregion HEADER - -InModuleScope $script:moduleName { - Describe 'Get-ClassResourceAst' { - BeforeAll { - $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' - - New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force - - $mockBuiltModuleScriptFilePath = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' - - # The class DSC resource in the built module. - $mockBuiltModuleScript = @' -class MyBaseClass -{ - [void] MyHelperFunction() {} -} - -[DscResource()] -class AzDevOpsProject -{ - [AzDevOpsProject] Get() - { - return [AzDevOpsProject] $this - } - - [System.Boolean] Test() - { - return $true - } - - [void] Set() {} - - [DscProperty(Key)] - [System.String] $ProjectName -} - -[DscResource()] -class MyDscResource -{ - [MyDscResource] Get() - { - return [MyDscResource] $this - } - - [System.Boolean] Test() - { - return $true - } - - [void] Set() {} - - [DscProperty(Key)] - [System.String] $ProjectName -} -'@ - - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath $mockBuiltModuleScriptFilePath -Encoding ascii -Force - } - - Context 'When returning all DSC class resources in the script file' { - It 'Should return the correct classes' { - $astResult = Get-ClassResourceAst -ScriptFile $mockBuiltModuleScriptFilePath - - $astResult | Should -HaveCount 2 - $astResult.Name | Should -Contain 'MyDscResource' - $astResult.Name | Should -Contain 'AzDevOpsProject' - } - } - - Context 'When returning a single DSC class resource from the script file' { - It 'Should return the correct classes' { - $astResult = Get-ClassResourceAst -ScriptFile $mockBuiltModuleScriptFilePath -ClassName 'MyDscResource' - - $astResult | Should -HaveCount 1 - $astResult.Name | Should -Be 'MyDscResource' - } - } - } -} diff --git a/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 b/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 deleted file mode 100644 index 55d55bb1..00000000 --- a/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 +++ /dev/null @@ -1,591 +0,0 @@ -#region HEADER -$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path -$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { - ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and - $(try - { - Test-ModuleManifest -Path $_.FullName -ErrorAction Stop - } - catch - { - $false - }) - }).BaseName - -$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 -Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' - -Import-Module $script:moduleName -Force -ErrorAction 'Stop' -#endregion HEADER - -InModuleScope $script:moduleName { - Describe 'Get-ClassResourceProperty' { - Context 'When the resource has a parent class that also has a DSC property' { - BeforeAll { - $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' - $mockSourcePath = Join-Path -Path $TestDrive -ChildPath 'source' - - New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force - New-Item -Path "$mockSourcePath\Classes" -ItemType 'Directory' -Force - - # The class DSC resource in the built module. - $mockBuiltModuleScript = @' -class ResourceBase -{ - hidden [System.String] $NotADscProperty - - [DscProperty()] - [System.String] - $Ensure -} - -[DscResource()] -class MyDscResource : ResourceBase -{ - [MyDscResource] Get() - { - return [MyDscResource] $this - } - - [System.Boolean] Test() - { - return $true - } - - [void] Set() {} - - [DscProperty(Key)] - [System.String] $ProjectName - - [DscProperty()] - [ValidateSet('Up', 'Down')] - [System.String[]] $ValidateSetProperty -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockBuiltModulePath\MyClassModule.psm1" -Encoding ascii -Force - - <# - The source file of class DSC resource. This file is not actually - referencing the base class to simplify the tests. - The property ValidateSetProperty does not have a parameter description - to be able to test missing description. - #> - $mockResourceSourceScript = @' -<# - .SYNOPSIS - Resource synopsis. - - .DESCRIPTION - Resource description. - - .PARAMETER ProjectName - ProjectName description. -#> -[DscResource()] -class MyDscResource -{ - [MyDscResource] Get() - { - return [MyDscResource] $this - } - - [System.Boolean] Test() - { - return $true - } - - [void] Set() {} - - [DscProperty(Key)] - [System.String] $ProjectName - - [DscProperty()] - [ValidateSet('Up', 'Down')] - [System.String[]] $ValidateSetProperty -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockResourceSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\010.MyDscResource.ps1" -Encoding ascii -Force - - $mockBaseClassSourceScript = @' -<# - .SYNOPSIS - Synopsis for base class. - - .DESCRIPTION - Description for base class - - .PARAMETER Ensure - Ensure description. -#> -class ResourceBase -{ - hidden [System.String] $NotADscProperty - - [DscProperty()] - [System.String] - $Ensure -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockBaseClassSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\001.ResourceBase.ps1" -Encoding ascii -Force - } - - It 'Should return the expected DSC class resource properties' { - $mockGetClassResourcePropertyParameters = @{ - SourcePath = $mockSourcePath - BuiltModuleScriptFilePath = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' - ClassName = @( - 'ResourceBase' - 'MyDscResource' - ) - } - - $getClassResourcePropertyResult = Get-ClassResourceProperty @mockGetClassResourcePropertyParameters - $getClassResourcePropertyResult | Should -HaveCount 3 - $getClassResourcePropertyResult.Name | Should -Contain 'Ensure' - $getClassResourcePropertyResult.Name | Should -Contain 'ProjectName' - $getClassResourcePropertyResult.Name | Should -Contain 'ValidateSetProperty' - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'Ensure'}) - $ensurePropertyResult.State | Should -Be 'Write' - $ensurePropertyResult.Description | Should -Be 'Ensure description.' - $ensurePropertyResult.DataType | Should -Be 'System.String' - $ensurePropertyResult.IsArray | Should -BeFalse - $ensurePropertyResult.ValueMap | Should -BeNullOrEmpty - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'ProjectName'}) - $ensurePropertyResult.State | Should -Be 'Key' - $ensurePropertyResult.Description | Should -Be 'ProjectName description.' - $ensurePropertyResult.DataType | Should -Be 'System.String' - $ensurePropertyResult.IsArray | Should -BeFalse - $ensurePropertyResult.ValueMap | Should -BeNullOrEmpty - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'ValidateSetProperty'}) - $ensurePropertyResult.State | Should -Be 'Write' - $ensurePropertyResult.Description | Should -BeNullOrEmpty - $ensurePropertyResult.DataType | Should -Be 'System.String[]' - $ensurePropertyResult.IsArray | Should -BeFalse - $ensurePropertyResult.ValueMap | Should -Contain 'Up' - $ensurePropertyResult.ValueMap | Should -Contain 'Down' - } - } - } - - Context 'When the resource has a parent class that does not have a source file (part of another module)' { - BeforeAll { - $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' - $mockSourcePath = Join-Path -Path $TestDrive -ChildPath 'source' - - New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force - New-Item -Path "$mockSourcePath\Classes" -ItemType 'Directory' -Force - - # The class DSC resource in the built module. - $mockBuiltModuleScript = @' -class ResourceBase -{ - hidden [System.String] $NotADscProperty - - [DscProperty()] - [System.String] - $Ensure -} - -[DscResource()] -class MyDscResource : ResourceBase -{ - [MyDscResource] Get() - { - return [MyDscResource] $this - } - - [System.Boolean] Test() - { - return $true - } - - [void] Set() {} - - [DscProperty(Key)] - [System.String] $ProjectName - - [DscProperty()] - [ValidateSet('Up', 'Down')] - [System.String[]] $ValidateSetProperty -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockBuiltModulePath\MyClassModule.psm1" -Encoding ascii -Force - - <# - The source file of class DSC resource. This file is not actually - referencing the base class to simplify the tests. - The property ValidateSetProperty does not have a parameter description - to be able to test missing description. - #> - $mockResourceSourceScript = @' -<# -.SYNOPSIS -Resource synopsis. - -.DESCRIPTION -Resource description. - -.PARAMETER ProjectName -ProjectName description. -#> -[DscResource()] -class MyDscResource -{ -[MyDscResource] Get() -{ - return [MyDscResource] $this -} - -[System.Boolean] Test() -{ - return $true -} - -[void] Set() {} - -[DscProperty(Key)] -[System.String] $ProjectName - -[DscProperty()] -[ValidateSet('Up', 'Down')] -[System.String[]] $ValidateSetProperty -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockResourceSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\010.MyDscResource.ps1" -Encoding ascii -Force - - It 'Should return the expected DSC class resource properties' { - $mockGetClassResourcePropertyParameters = @{ - SourcePath = $mockSourcePath - BuiltModuleScriptFilePath = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' - ClassName = @( - 'ResourceBase' - 'MyDscResource' - ) - } - - $getClassResourcePropertyResult = Get-ClassResourceProperty @mockGetClassResourcePropertyParameters - $getClassResourcePropertyResult | Should -HaveCount 2 - $getClassResourcePropertyResult.Name | Should -Contain 'ProjectName' - $getClassResourcePropertyResult.Name | Should -Contain 'ValidateSetProperty' - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'ProjectName'}) - $ensurePropertyResult.State | Should -Be 'Key' - $ensurePropertyResult.Description | Should -Be 'ProjectName description.' - $ensurePropertyResult.DataType | Should -Be 'System.String' - $ensurePropertyResult.IsArray | Should -BeFalse - $ensurePropertyResult.ValueMap | Should -BeNullOrEmpty - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'ValidateSetProperty'}) - $ensurePropertyResult.State | Should -Be 'Write' - $ensurePropertyResult.Description | Should -BeNullOrEmpty - $ensurePropertyResult.DataType | Should -Be 'System.String[]' - $ensurePropertyResult.IsArray | Should -BeFalse - $ensurePropertyResult.ValueMap | Should -Contain 'Up' - $ensurePropertyResult.ValueMap | Should -Contain 'Down' - } - } - } - - Context 'When a base class is missing comment-based help' { - BeforeAll { - $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' - $mockSourcePath = Join-Path -Path $TestDrive -ChildPath 'source' - - New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force - New-Item -Path "$mockSourcePath\Classes" -ItemType 'Directory' -Force - - # The class DSC resource in the built module. - $mockBuiltModuleScript = @' -class ResourceBase -{ - hidden [System.String] $NotADscProperty - - [DscProperty()] - [System.String] - $Ensure -} - -[DscResource()] -class MyDscResource : ResourceBase -{ - [MyDscResource] Get() - { - return [MyDscResource] $this - } - - [System.Boolean] Test() - { - return $true - } - - [void] Set() {} - - [DscProperty(Key)] - [System.String] $ProjectName - - [DscProperty()] - [System.String] $DescriptionTestProperty -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockBuiltModulePath\MyClassModule.psm1" -Encoding ascii -Force - - <# - The source file of class DSC resource. This file is not actually - referencing the base class to simplify the tests. - - The property DescriptionTestProperty is used to test description - parsing. - #> - $mockResourceSourceScript = @' -<# -.SYNOPSIS - Resource synopsis. - - .DESCRIPTION - Resource description. - - .PARAMETER ProjectName - ProjectName description. - - .PARAMETER DescriptionTestProperty - DescriptionTestProperty description. - - This is a second row with | various tests like double space and vertical bar. -#> -[DscResource()] -class MyDscResource -{ - [MyDscResource] Get() - { - return [MyDscResource] $this - } - - [System.Boolean] Test() - { - return $true - } - - [void] Set() {} - - [DscProperty(Key)] - [System.String] $ProjectName - - [DscProperty()] - [System.String] $DescriptionTestProperty -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockResourceSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\010.MyDscResource.ps1" -Encoding ascii -Force - - $mockBaseClassSourceScript = @' -class ResourceBase -{ - hidden [System.String] $NotADscProperty - - [DscProperty()] - [System.String] - $Ensure -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockBaseClassSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\001.ResourceBase.ps1" -Encoding ascii -Force - } - - It 'Should return the expected DSC class resource properties' { - $mockGetClassResourcePropertyParameters = @{ - SourcePath = $mockSourcePath - BuiltModuleScriptFilePath = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' - ClassName = @( - 'ResourceBase' - 'MyDscResource' - ) - } - - $getClassResourcePropertyResult = Get-ClassResourceProperty @mockGetClassResourcePropertyParameters - $getClassResourcePropertyResult | Should -HaveCount 3 - $getClassResourcePropertyResult.Name | Should -Contain 'Ensure' - $getClassResourcePropertyResult.Name | Should -Contain 'ProjectName' - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'Ensure'}) - $ensurePropertyResult.State | Should -Be 'Write' - $ensurePropertyResult.Description | Should -BeNullOrEmpty - $ensurePropertyResult.DataType | Should -Be 'System.String' - $ensurePropertyResult.IsArray | Should -BeFalse - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'ProjectName'}) - $ensurePropertyResult.State | Should -Be 'Key' - $ensurePropertyResult.Description | Should -Be 'ProjectName description.' - $ensurePropertyResult.DataType | Should -Be 'System.String' - $ensurePropertyResult.IsArray | Should -BeFalse - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'DescriptionTestProperty'}) - $ensurePropertyResult.State | Should -Be 'Write' - $ensurePropertyResult.Description | Should -BeExactly @' -DescriptionTestProperty description. This is a second row with various tests like double space and vertical bar. -'@ - $ensurePropertyResult.DataType | Should -Be 'System.String' - $ensurePropertyResult.IsArray | Should -BeFalse - } - } - - Context 'When two script file names end with similar name' { - BeforeAll { - $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' - $mockSourcePath = Join-Path -Path $TestDrive -ChildPath 'source' - - New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force - New-Item -Path "$mockSourcePath\Classes" -ItemType 'Directory' -Force - - # The class DSC resource in the built module. - $mockBuiltModuleScript = @' -class BaseMyDscResource -{ -hidden [System.String] $NotADscProperty - -[DscProperty()] -[System.String] -$Ensure -} - -[DscResource()] -class MyDscResource : BaseMyDscResource -{ -[MyDscResource] Get() -{ - return [MyDscResource] $this -} - -[System.Boolean] Test() -{ - return $true -} - -[void] Set() {} - -[DscProperty(Key)] -[System.String] $ProjectName - -[DscProperty()] -[ValidateSet('Up', 'Down')] -[System.String[]] $ValidateSetProperty -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockBuiltModulePath\MyClassModule.psm1" -Encoding ascii -Force - - <# - The source file of class DSC resource. This file is not actually - referencing the base class to simplify the tests. - The property ValidateSetProperty does not have a parameter description - to be able to test missing description. - #> - $mockResourceSourceScript = @' -<# -.SYNOPSIS -Resource synopsis. - -.DESCRIPTION -Resource description. - -.PARAMETER ProjectName -ProjectName description. -#> -[DscResource()] -class MyDscResource -{ -[MyDscResource] Get() -{ - return [MyDscResource] $this -} - -[System.Boolean] Test() -{ - return $true -} - -[void] Set() {} - -[DscProperty(Key)] -[System.String] $ProjectName - -[DscProperty()] -[ValidateSet('Up', 'Down')] -[System.String[]] $ValidateSetProperty -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockResourceSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\010.MyDscResource.ps1" -Encoding ascii -Force - - $mockBaseClassSourceScript = @' -<# -.SYNOPSIS -Synopsis for base class. - -.DESCRIPTION -Description for base class - -.PARAMETER Ensure -Ensure description. -#> -class BaseMyDscResource -{ -hidden [System.String] $NotADscProperty - -[DscProperty()] -[System.String] -$Ensure -} -'@ - # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. - $mockBaseClassSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\001.BaseMyDscResource.ps1" -Encoding ascii -Force - } - - It 'Should return the expected DSC class resource properties' { - $mockGetClassResourcePropertyParameters = @{ - SourcePath = $mockSourcePath - BuiltModuleScriptFilePath = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' - ClassName = @( - 'MyDscResource' - 'BaseMyDscResource' - ) - } - - $getClassResourcePropertyResult = Get-ClassResourceProperty @mockGetClassResourcePropertyParameters - $getClassResourcePropertyResult | Should -HaveCount 3 - $getClassResourcePropertyResult.Name | Should -Contain 'Ensure' - $getClassResourcePropertyResult.Name | Should -Contain 'ProjectName' - $getClassResourcePropertyResult.Name | Should -Contain 'ValidateSetProperty' - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'Ensure'}) - $ensurePropertyResult.State | Should -Be 'Write' - $ensurePropertyResult.Description | Should -Be 'Ensure description.' - $ensurePropertyResult.DataType | Should -Be 'System.String' - $ensurePropertyResult.IsArray | Should -BeFalse - $ensurePropertyResult.ValueMap | Should -BeNullOrEmpty - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'ProjectName'}) - $ensurePropertyResult.State | Should -Be 'Key' - $ensurePropertyResult.Description | Should -Be 'ProjectName description.' - $ensurePropertyResult.DataType | Should -Be 'System.String' - $ensurePropertyResult.IsArray | Should -BeFalse - $ensurePropertyResult.ValueMap | Should -BeNullOrEmpty - - $ensurePropertyResult = $getClassResourcePropertyResult.Where({$_.Name -eq 'ValidateSetProperty'}) - $ensurePropertyResult.State | Should -Be 'Write' - $ensurePropertyResult.Description | Should -BeNullOrEmpty - $ensurePropertyResult.DataType | Should -Be 'System.String[]' - $ensurePropertyResult.IsArray | Should -BeFalse - $ensurePropertyResult.ValueMap | Should -Contain 'Up' - $ensurePropertyResult.ValueMap | Should -Contain 'Down' - } - } -} From d3e3dbbeba3a49985f9b8f8565a7ae6351435b52 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Fri, 25 Oct 2024 17:32:56 +0100 Subject: [PATCH 04/45] Update changelog --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8eb152ea..062f4cff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Removed - Removed `build.psd1` as it is no longer required to build the project. +- Removed ClassAst functions + - `Get-ClassResourceProperty` + - `Get-ClassAst` + - `Get-ClassResourceAst` ### Added @@ -42,6 +46,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Task `Generate_Markdown_For_DSC_Resources` - Outputs a warning message if the old configuration key is used in the build configuration but keeps using the old configuration key. +- `New-DscClassResourcePage` + - Remove using Ast to generate documentation. Fixes [#116](https://github.com/dsccommunity/DscResource.DocGenerator/issues/116). + - Order properties correctly fixes [#126](https://github.com/dsccommunity/DscResource.DocGenerator/issues/126). ### Fixed From e480d0f72b3fc8bafe36affe88dbabb81a14d214 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Mon, 28 Oct 2024 09:46:53 +0000 Subject: [PATCH 05/45] Fix HQRM --- source/Private/Get-ClassPropertyCustomAttribute.ps1 | 8 +++++--- source/Private/Get-DscPropertyType.ps1 | 2 +- source/Private/Get-DscResourceSchemaPropertyContent.ps1 | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/source/Private/Get-ClassPropertyCustomAttribute.ps1 b/source/Private/Get-ClassPropertyCustomAttribute.ps1 index 402381f2..e69b4073 100644 --- a/source/Private/Get-ClassPropertyCustomAttribute.ps1 +++ b/source/Private/Get-ClassPropertyCustomAttribute.ps1 @@ -1,4 +1,5 @@ -function Get-ClassPropertyCustomAttribute { +function Get-ClassPropertyCustomAttribute +{ [CmdletBinding()] param ( [Parameter(Mandatory = $true)] @@ -10,7 +11,8 @@ function Get-ClassPropertyCustomAttribute { $AttributeType ) - process { - return $Attributes | Where-Object {$_.AttributeType.Name -eq $AttributeType} + process + { + return $Attributes | Where-Object { $_.AttributeType.Name -eq $AttributeType } } } diff --git a/source/Private/Get-DscPropertyType.ps1 b/source/Private/Get-DscPropertyType.ps1 index e1f7b50e..f6900072 100644 --- a/source/Private/Get-DscPropertyType.ps1 +++ b/source/Private/Get-DscPropertyType.ps1 @@ -23,7 +23,7 @@ function Get-DscPropertyType { return $PropertyType.GenericTypeArguments.Name } - Default + default { return $PropertyType.Name } diff --git a/source/Private/Get-DscResourceSchemaPropertyContent.ps1 b/source/Private/Get-DscResourceSchemaPropertyContent.ps1 index 1650b4e3..494f7e84 100644 --- a/source/Private/Get-DscResourceSchemaPropertyContent.ps1 +++ b/source/Private/Get-DscResourceSchemaPropertyContent.ps1 @@ -59,8 +59,9 @@ function Get-DscResourceSchemaPropertyContent 'Read' ) - foreach ($key in $sortOrder) { - $orderedProperties += $Property.GetEnumerator() | Where-Object {$_.State -eq $key} | Sort-Object {$_.Name} + foreach ($key in $sortOrder) + { + $orderedProperties += $Property.GetEnumerator() | Where-Object { $_.State -eq $key } | Sort-Object { $_.Name } } foreach ($currentProperty in $orderedProperties) From 6d0cadbd7d2dddf0628c5e61acd25e41ee6c90fe Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 15:00:16 +0000 Subject: [PATCH 06/45] Update help --- ...Test-ClassPropertyDscAttributeArgument.ps1 | 27 +++---------------- 1 file changed, 4 insertions(+), 23 deletions(-) diff --git a/source/Private/Test-ClassPropertyDscAttributeArgument.ps1 b/source/Private/Test-ClassPropertyDscAttributeArgument.ps1 index 27e3d175..fb6f44aa 100644 --- a/source/Private/Test-ClassPropertyDscAttributeArgument.ps1 +++ b/source/Private/Test-ClassPropertyDscAttributeArgument.ps1 @@ -7,9 +7,9 @@ This function returns the property state value of an DSC class-based resource property. - .PARAMETER Ast - The Abstract Syntax Tree (AST) for class-based DSC resource property. - The passed value must be an AST of the type 'PropertyMemberAst'. + .PARAMETER PropertyAttributes + The PropertyAttributes for class-based DSC resource property. + The passed value must be of the type 'System.Reflection.CustomAttributeData'. .PARAMETER IsKey Specifies if the parameter is expected to have the type qualifier Key. @@ -24,30 +24,11 @@ Specifies if the parameter is expected to have the type qualifier Read. .EXAMPLE - Test-PropertyMemberAst -IsKey -Ast { - [DscResource()] - class NameOfResource { - [DscProperty(Key)] - [string] $KeyName - - [NameOfResource] Get() { - return $this - } - - [void] Set() {} - - [bool] Test() { - return $true - } - } - }.Ast.Find({$args[0] -is [System.Management.Automation.Language.PropertyMemberAst]}, $false) + Test-ClassPropertyDscAttributeArgument -IsKey -PropertyAttributes $properties Returns $true that the property 'KeyName' is Key. #> -# From provided CustomAttribute -# Return desired Dsc value if true e.g. Key|Mandatory|Read|Write - function Test-ClassPropertyDscAttributeArgument { [CmdletBinding()] From d194522d501a3463774a2fb038dc12acc3fdcbee Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 15:00:35 +0000 Subject: [PATCH 07/45] Remove unused function --- .../Private/Get-ClassResourcePropertyNew.ps1 | 165 ------------------ 1 file changed, 165 deletions(-) delete mode 100644 source/Private/Get-ClassResourcePropertyNew.ps1 diff --git a/source/Private/Get-ClassResourcePropertyNew.ps1 b/source/Private/Get-ClassResourcePropertyNew.ps1 deleted file mode 100644 index 70a1027c..00000000 --- a/source/Private/Get-ClassResourcePropertyNew.ps1 +++ /dev/null @@ -1,165 +0,0 @@ -<# - .SYNOPSIS - Returns DSC class resource properties from the provided class or classes. - - .DESCRIPTION - Returns DSC class resource properties from the provided class or classes. - - .PARAMETER SourcePath - The path to the source folder (in which the child folder 'Classes' exist). - - .PARAMETER BuiltModuleScriptFilePath - The path to the built module script file that contains the class. - - .PARAMETER ClassName - One or more class names to return properties for. - - .EXAMPLE - Get-ClassResourceProperty -ClassName @('myParentClass', 'myClass') -BuiltModuleScriptFilePath '.\output\MyModule\1.0.0\MyModule.psm1' -SourcePath '.\source' - - Returns all DSC class resource properties. -#> -function Get-ClassResourcePropertyNew -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable[]])] - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $SourcePath, - - # [Parameter(Mandatory = $true)] - # [System.String] - # $BuiltModuleScriptFilePath, - - [Parameter(Mandatory = $true)] - [System.Reflection.PropertyInfo[]] - $Properties - - - ) - - $resourceProperty = [System.Collections.Hashtable[]] @() - - $className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name - - foreach ($currentClassName in $className) - { - #$dscResourceAst = Get-ClassAst -ClassName $currentClassName -ScriptFile $BuiltModuleScriptFilePath - - $classExists = $false - $sourceFilePath = '' - $childPaths = @( - ('Classes/???.{0}.ps1' -f $currentClassName) - ('Classes/{0}.ps1' -f $currentClassName) - ) - - foreach ($childPath in $childPaths) - { - $sourceFilePath = Join-Path -Path $SourcePath -ChildPath $childPath - - if ((Test-Path -Path $sourceFilePath)) - { - $classExists = $true - break - } - } - - <# - Skip if the class's source file does not exist. This can happen if the - class uses a parent class from a different module. - #> - if (-not $classExists) - { - continue - } - - $dscResourceCommentBasedHelp = Get-CommentBasedHelp -Path $sourceFilePath - - # $astFilter = { - # $args[0] -is [System.Management.Automation.Language.PropertyMemberAst] ` - # -and $args[0].Attributes.TypeName.Name -eq 'DscProperty' - # } - - # $propertyMemberAsts = $dscResourceAst.FindAll($astFilter, $true) - $propertyMembers = $Properties | Where-Object { $_.DeclaringType.Name -eq $currentClassName } - - <# - Looping through each resource property to build the resulting - hashtable. Hashtable will be in the format: - - @{ - Name = - State = 'Key' | 'Required' |'Write' | 'Read' - Description = - EmbeddedInstance = 'MSFT_Credential' | $null - DataType = 'System.String' | 'System.String[] | etc. - IsArray = $true | $false - ValueMap = @( | ...) - } - #> - foreach ($propertyMember in $propertyMembers) - { - Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMember.Name, $currentClassName) - - $propertyAttribute = @{ - Name = $propertyMember.Name - DataType = Get-DscPropertyType -PropertyType $propertyMember.PropertyType - - # Always set to null, correct type name is set in DataType. - EmbeddedInstance = $null - - # Always set to $false - correct type name is set in DataType. - IsArray = $false - } - - $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember - - $valueMapValues = $null - if ($propertyMember.PropertyType.IsEnum) - { - $valueMapValues = $propertyMember.PropertyType.GetEnumNames() - } - - $validateSet = Get-ClassPropertyCustomAttribute -Attributes $propertyMember.CustomAttributes -AttributeType 'ValidateSetAttribute' - if ($validateSet) - { - $valueMapValues = $validateSet.ConstructorArguments.Value.Value - } - - if ($valueMapValues) - { - $propertyAttribute.ValueMap = $valueMapValues - } - - if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0) - { - # The key name must be upper-case for it to match the right item in the list of parameters. - $propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMember.Name.ToUpper()] - - if ($propertyDescription) - { - $propertyDescription = Format-Text -Text $propertyDescription -Format @( - 'Remove_Blank_Rows_At_End_Of_String', - 'Remove_Indentation_From_Blank_Rows', - 'Replace_NewLine_With_One_Whitespace', - 'Replace_Vertical_Bar_With_One_Whitespace', - 'Replace_Multiple_Whitespace_With_One', - 'Remove_Whitespace_From_End_Of_String' - ) - } - } - else - { - $propertyDescription = '' - } - - $propertyAttribute.Description = $propertyDescription - - $resourceProperty += $propertyAttribute - } - } - - return $resourceProperty -} From 95c1c693c29c182f09812176a36202b0d5ab70f0 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 15:16:18 +0000 Subject: [PATCH 08/45] Remove blank lines and fix build warning message --- build.yaml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/build.yaml b/build.yaml index 301f621d..ea51641f 100644 --- a/build.yaml +++ b/build.yaml @@ -71,8 +71,6 @@ BuildWorkflow: Remove-Module -Name 'DscResource.DocGenerator' -ErrorAction SilentlyContinue } - - #################################################### # PESTER Configuration # #################################################### @@ -141,6 +139,16 @@ DscResource.DocGenerator: - '\*(.+?)\*' # Match Italic (asterisk) Publish_GitHub_Wiki_Content: Debug: true + Generate_Markdown_For_DSC_Resources: + MofResourceMetadata: + Type: MofResource + Category: Resources + ClassResourceMetadata: + Type: ClassResource + Category: Resources + CompositeResourceMetadata: + Type: CompositeResource + Category: Resources Generate_Wiki_Sidebar: Debug: false AlwaysOverwrite: true From 880548e9a3d087b1f8512323b83b2d17fcb41d3e Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 15:19:00 +0000 Subject: [PATCH 09/45] Remove commented code --- source/Private/New-DscClassResourceWikiPage.ps1 | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/source/Private/New-DscClassResourceWikiPage.ps1 b/source/Private/New-DscClassResourceWikiPage.ps1 index 922e3752..c7bc2bae 100644 --- a/source/Private/New-DscClassResourceWikiPage.ps1 +++ b/source/Private/New-DscClassResourceWikiPage.ps1 @@ -100,7 +100,6 @@ function New-DscClassResourceWikiPage Write-Verbose -Message ($script:localizedData.FoundClassBasedMessage -f $dscClassesInModule.Count, $builtModuleScriptFile.FullName) # Looping through each class-based resource. - # TODO: Should this include non Dsc Classes? foreach ($dscClassInModule in $dscClassesInModule) { Write-Verbose -Message ($script:localizedData.GenerateWikiPageMessage -f $dscClassInModule.Name) @@ -131,11 +130,8 @@ function New-DscClassResourceWikiPage $dscProperties = $dscClassInModule.GetProperties() | Where-Object {'DscPropertyAttribute' -in $_.CustomAttributes.AttributeType.Name} - #$className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name - # Returns the properties for class and any existing parent class(es). - $resourceProperty = Get-ClassResourcePropertyNew -Properties $dscProperties -SourcePath $SourcePath - #$resourceProperty = Get-ClassResourcePropertyNew -ClassName $className -SourcePath $SourcePath -BuiltModuleScriptFilePath $builtModuleScriptFile.FullName + $resourceProperty = Get-ClassResourceProperty -Properties $dscProperties -SourcePath $SourcePath $propertyContent = Get-DscResourceSchemaPropertyContent -Property $resourceProperty -UseMarkdown From 9082c86c99ad1c44348ac37143bacd5293864522 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:29:28 +0000 Subject: [PATCH 10/45] Update expected parameter order --- .../unit/private/New-DscMofResourceWikiPage.Tests.ps1 | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/unit/private/New-DscMofResourceWikiPage.Tests.ps1 b/tests/unit/private/New-DscMofResourceWikiPage.Tests.ps1 index a4de6727..bfc8d67a 100644 --- a/tests/unit/private/New-DscMofResourceWikiPage.Tests.ps1 +++ b/tests/unit/private/New-DscMofResourceWikiPage.Tests.ps1 @@ -166,8 +166,8 @@ Second row of description. | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Id** | Key | String | Id Description | | -| **Enum** | Write | String | Enum Description. | `Value1`, `Value2`, `Value3` | | **Int** | Required | Uint32 | Int Description. | | +| **Enum** | Write | String | Enum Description. | `Value1`, `Value2`, `Value3` | | **Read** | Read | String | Read Description. | | ## Description @@ -777,8 +777,8 @@ Configuration Example | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Id** | Key | String | Id Description | | -| **Enum** | Write | String | Enum Description. | `Value1`, `Value2`, `Value3` | | **Int** | Required | Uint32 | Int Description. | | +| **Enum** | Write | String | Enum Description. | `Value1`, `Value2`, `Value3` | | **Read** | Read | String | Read Description. | | ### DSC_EmbeddedInstance @@ -788,8 +788,8 @@ Configuration Example | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **EmbeddedId** | Key | String | Id Description | | -| **EmbeddedEnum** | Write | String | Enum Description. | `Value1`, `Value2`, `Value3` | | **EmbeddedInt** | Required | Uint32 | Int Description. | | +| **EmbeddedEnum** | Write | String | Enum Description. | `Value1`, `Value2`, `Value3` | | **EmbeddedRead** | Read | String | Read Description. | | ## Description @@ -997,8 +997,8 @@ Type: MofResource | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **Id** | Key | String | Id Description | | -| **Enum** | Write | String | Enum Description. | `Value1`, `Value2`, `Value3` | | **Int** | Required | Uint32 | Int Description. | | +| **Enum** | Write | String | Enum Description. | `Value1`, `Value2`, `Value3` | | **Read** | Read | String | Read Description. | | ### DSC_EmbeddedInstance @@ -1008,8 +1008,8 @@ Type: MofResource | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **EmbeddedId** | Key | String | Id Description | | -| **EmbeddedEnum** | Write | String | Enum Description. | `Value1`, `Value2`, `Value3` | | **EmbeddedInt** | Required | Uint32 | Int Description. | | +| **EmbeddedEnum** | Write | String | Enum Description. | `Value1`, `Value2`, `Value3` | | **EmbeddedRead** | Read | String | Read Description. | | ## Description From 9b0fc575242791d66184cff8554f5951894dfdfd Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:30:23 +0000 Subject: [PATCH 11/45] Update parameter order --- .../private/Get-DscResourceSchemaPropertyContent.Tests.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/unit/private/Get-DscResourceSchemaPropertyContent.Tests.ps1 b/tests/unit/private/Get-DscResourceSchemaPropertyContent.Tests.ps1 index 846739a8..f9c88fc6 100644 --- a/tests/unit/private/Get-DscResourceSchemaPropertyContent.Tests.ps1 +++ b/tests/unit/private/Get-DscResourceSchemaPropertyContent.Tests.ps1 @@ -89,10 +89,10 @@ InModuleScope $script:moduleName { $result[1] | Should -Be '| --- | --- | --- | --- | --- |' $result[2] | Should -Be '| **StringProperty** | Key | String | Any description | |' $result[3] | Should -Be '| **StringValueMapProperty** | Key | String | Any description | Value1, Value2 |' - $result[4] | Should -Be '| **StringArrayProperty** | Write | String[] | Any description | |' - $result[5] | Should -Be '| **CredentialProperty** | Write | PSCredential | Any description | |' + $result[4] | Should -Be '| **CredentialProperty** | Write | PSCredential | Any description | |' + $result[5] | Should -Be '| **EmbeddedInstanceArrayProperty** | Write | DSC_Embedded2[] | Any description | |' $result[6] | Should -Be '| **EmbeddedInstanceProperty** | Write | DSC_Embedded1 | Any description | |' - $result[7] | Should -Be '| **EmbeddedInstanceArrayProperty** | Write | DSC_Embedded2[] | Any description | |' + $result[7] | Should -Be '| **StringArrayProperty** | Write | String[] | Any description | |' } } } From 61287442dfddc5b375d882d850a7c4384b4f42db Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:30:41 +0000 Subject: [PATCH 12/45] Add comment based help --- .../Get-ClassPropertyCustomAttribute.ps1 | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/source/Private/Get-ClassPropertyCustomAttribute.ps1 b/source/Private/Get-ClassPropertyCustomAttribute.ps1 index e69b4073..36e5ff39 100644 --- a/source/Private/Get-ClassPropertyCustomAttribute.ps1 +++ b/source/Private/Get-ClassPropertyCustomAttribute.ps1 @@ -1,6 +1,27 @@ +<# + .SYNOPSIS + This function returns a filtered list of CustomAttributes from a given AttributeType. + + .DESCRIPTION + The function will filter the provided CustomAttributes provided and returns only the matching attributes or null. + + .PARAMETER Attributes + The array of attributes that need to be filtered. + + .PARAMETER AttributeType + The attribute type name to filter the attributes on. + + .OUTPUTS + System.Reflection.CustomAttributeData[] + + .EXAMPLE + Get-ClassPropertyCustomAttribute -Attributes $CommonAttributes -AttributeType 'ValidateSetAttribute' +#> + function Get-ClassPropertyCustomAttribute { [CmdletBinding()] + [OutputType([System.Reflection.CustomAttributeData[]])] param ( [Parameter(Mandatory = $true)] [System.Reflection.CustomAttributeData[]] From eb7579cfe74ac890770aa0b664879c1c19e353f9 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:31:19 +0000 Subject: [PATCH 13/45] Add new helper function --- source/Private/Get-ClassResourceProperty.ps1 | 152 +++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 source/Private/Get-ClassResourceProperty.ps1 diff --git a/source/Private/Get-ClassResourceProperty.ps1 b/source/Private/Get-ClassResourceProperty.ps1 new file mode 100644 index 00000000..d5e24e6c --- /dev/null +++ b/source/Private/Get-ClassResourceProperty.ps1 @@ -0,0 +1,152 @@ +<# + .SYNOPSIS + Returns DSC class resource properties from the provided PropertyInfo properties. + + .DESCRIPTION + Returns DSC class resource properties from the provided PropertyInfo properties. + + .PARAMETER SourcePath + The path to the source folder (in which the child folder 'Classes' exist). + + .PARAMETER Properties + One or more PropertyInfo objects return properties for. + + .OUTPUTS + System.Collections.Hashtable[] + + .EXAMPLE + Get-ClassResourceProperty -Properties $PropertyInfos -SourcePath '.\source' + + Returns all DSC class resource properties. +#> +function Get-ClassResourceProperty +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable[]])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $SourcePath, + + [Parameter(Mandatory = $true)] + [System.Reflection.PropertyInfo[]] + $Properties + ) + + $resourceProperty = [System.Collections.Hashtable[]] @() + + $className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name + + foreach ($currentClassName in $className) + { + $classExists = $false + $sourceFilePath = '' + $childPaths = @( + ('Classes/???.{0}.ps1' -f $currentClassName) + ('Classes/{0}.ps1' -f $currentClassName) + ) + + foreach ($childPath in $childPaths) + { + $sourceFilePath = Join-Path -Path $SourcePath -ChildPath $childPath + + if ((Test-Path -Path $sourceFilePath)) + { + $classExists = $true + break + } + } + + <# + Skip if the class's source file does not exist. This can happen if the + class uses a parent class from a different module. + #> + if (-not $classExists) + { + continue + } + + $dscResourceCommentBasedHelp = Get-CommentBasedHelp -Path $sourceFilePath + + $propertyMembers = $Properties | Where-Object { $_.DeclaringType.Name -eq $currentClassName } + + <# + Looping through each resource property to build the resulting + hashtable. Hashtable will be in the format: + + @{ + Name = + State = 'Key' | 'Required' |'Write' | 'Read' + Description = + EmbeddedInstance = 'MSFT_Credential' | $null + DataType = 'System.String' | 'System.String[] | etc. + IsArray = $true | $false + ValueMap = @( | ...) + } + #> + foreach ($propertyMember in $propertyMembers) + { + Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMember.Name, $currentClassName) + + $propertyAttribute = @{ + Name = $propertyMember.Name + DataType = Get-DscPropertyType -PropertyType $propertyMember.PropertyType + + # Always set to null, correct type name is set in DataType. + EmbeddedInstance = $null + + # Always set to $false - correct type name is set in DataType. + IsArray = $false + } + + $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember + Write-Warning ('Property {0} State = {1}' -f $propertyMember.Name, $propertyAttribute.State) + + $valueMapValues = $null + if ($propertyMember.PropertyType.IsEnum) + { + $valueMapValues = $propertyMember.PropertyType.GetEnumNames() + } + + $validateSet = Get-ClassPropertyCustomAttribute -Attributes $propertyMember.CustomAttributes -AttributeType 'ValidateSetAttribute' + if ($validateSet) + { + $valueMapValues = $validateSet.ConstructorArguments.Value.Value + } + + if ($valueMapValues) + { + $propertyAttribute.ValueMap = $valueMapValues + } + + if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0) + { + # The key name must be upper-case for it to match the right item in the list of parameters. + $propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMember.Name.ToUpper()] + + if ($propertyDescription) + { + $propertyDescription = Format-Text -Text $propertyDescription -Format @( + 'Remove_Blank_Rows_At_End_Of_String', + 'Remove_Indentation_From_Blank_Rows', + 'Replace_NewLine_With_One_Whitespace', + 'Replace_Vertical_Bar_With_One_Whitespace', + 'Replace_Multiple_Whitespace_With_One', + 'Remove_Whitespace_From_End_Of_String' + ) + } + } + else + { + $propertyDescription = '' + } + + $propertyAttribute.Description = $propertyDescription + + $resourceProperty += $propertyAttribute + } + } + + return $resourceProperty +} From 7c74acb149983492040ec438168de036b109453b Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:31:38 +0000 Subject: [PATCH 14/45] Fix additional indentation --- build.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.yaml b/build.yaml index ea51641f..34eef42e 100644 --- a/build.yaml +++ b/build.yaml @@ -15,11 +15,11 @@ Prefix: ./prefix.ps1 #################################################### NestedModule: - DscResource.Common: - CopyOnly: true - Path: ./output/RequiredModules/DscResource.Common - AddToManifest: false - Exclude: PSGetModuleInfo.xml + DscResource.Common: + CopyOnly: true + Path: ./output/RequiredModules/DscResource.Common + AddToManifest: false + Exclude: PSGetModuleInfo.xml #################################################### # Sampler Pipeline Configuration # From d199d20581aa953dbd551b30df9f1753b0a71c36 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:32:02 +0000 Subject: [PATCH 15/45] Add comment based help and use fullname --- source/Private/Get-DscPropertyType.ps1 | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/source/Private/Get-DscPropertyType.ps1 b/source/Private/Get-DscPropertyType.ps1 index f6900072..0aeb35a4 100644 --- a/source/Private/Get-DscPropertyType.ps1 +++ b/source/Private/Get-DscPropertyType.ps1 @@ -1,11 +1,21 @@ +<# + .SYNOPSIS + Retrieves the property type from a System.Type PropertyType object. + .DESCRIPTION + This function returns the property type as a string. This unwaps any string that has the Nullable property attribute. -# takes a System.RuntimeType - a System.Reflection.PropertyInfo .PropertyType + .PARAMETER PropertyType + The property to retrieve the property name from. -# Check PropertyType.Name = 'Nullable`1' -# Get value from GenericTypeArgument.FullName + .OUTPUTS + System.String -# else return FullName + .EXAMPLE + Get-DscPropertyType -PropertyType $VariableOfProperty. + + Returns the property type as a string. +#> function Get-DscPropertyType { @@ -21,11 +31,11 @@ function Get-DscPropertyType { 'Nullable`1' { - return $PropertyType.GenericTypeArguments.Name + return $PropertyType.GenericTypeArguments.FullName } default { - return $PropertyType.Name + return $PropertyType.FullName } } } From e84bbe773b7e75bd33f603ca3acf046240cb8d37 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:33:12 +0000 Subject: [PATCH 16/45] Update expected parameter order --- tests/unit/private/New-DscClassResourceWikiPage.Tests.ps1 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/private/New-DscClassResourceWikiPage.Tests.ps1 b/tests/unit/private/New-DscClassResourceWikiPage.Tests.ps1 index d797e21d..d4a4b324 100644 --- a/tests/unit/private/New-DscClassResourceWikiPage.Tests.ps1 +++ b/tests/unit/private/New-DscClassResourceWikiPage.Tests.ps1 @@ -525,9 +525,9 @@ class AzDevOpsProject | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | | **ProjectName** | Key | System.String | ProjectName description. | | +| **MandatoryProperty** | Required | System.String | MandatoryProperty description. | | | **ProjectId** | Write | System.String | ProjectId description. Second row with text. | | | **ValidateSetProperty** | Write | System.String | | `Up`, `Down` | -| **MandatoryProperty** | Required | System.String | MandatoryProperty description. | | | **Reasons** | Read | String[] | Reasons description. | | ## Description @@ -704,11 +704,11 @@ class ResourceBase | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | -| **Ensure** | Write | System.String | Ensure description. | | | **ProjectName** | Key | System.String | ProjectName description. | | +| **MandatoryProperty** | Required | System.String | MandatoryProperty description. | | +| **Ensure** | Write | System.String | Ensure description. | | | **ProjectId** | Write | System.String | ProjectId description. Second row with text. | | | **ValidateSetProperty** | Write | System.String | | `Up`, `Down` | -| **MandatoryProperty** | Required | System.String | MandatoryProperty description. | | | **Reasons** | Read | String[] | Reasons description. | | ## Description @@ -830,8 +830,8 @@ class ResourceBase | Parameter | Attribute | DataType | Description | Allowed Values | | --- | --- | --- | --- | --- | -| **Ensure** | Write | System.String | | | | **ProjectName** | Key | System.String | ProjectName description. | | +| **Ensure** | Write | System.String | | | ## Description From df1d9d7ed9da49f03bd00921992f88457d5bce8d Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:41:20 +0000 Subject: [PATCH 17/45] Use correct docs tasks --- build.yaml | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/build.yaml b/build.yaml index 34eef42e..01100435 100644 --- a/build.yaml +++ b/build.yaml @@ -36,19 +36,17 @@ BuildWorkflow: - Build_NestedModules_ModuleBuilder - Create_changelog_release_output - pack: - - build - - docs - - package_module_nupkg - docs: - Generate_Conceptual_Help - Generate_Wiki_Content - - Generate_Markdown_For_Public_Commands - - Generate_External_Help_File_For_Public_Commands - Generate_Wiki_Sidebar - - Clean_Markdown_Of_Public_Commands - Clean_Markdown_Metadata + - Package_Wiki_Content + + pack: + - build + - docs + - package_module_nupkg hqrmtest: - DscResource_Tests_Stop_On_Fail @@ -139,16 +137,6 @@ DscResource.DocGenerator: - '\*(.+?)\*' # Match Italic (asterisk) Publish_GitHub_Wiki_Content: Debug: true - Generate_Markdown_For_DSC_Resources: - MofResourceMetadata: - Type: MofResource - Category: Resources - ClassResourceMetadata: - Type: ClassResource - Category: Resources - CompositeResourceMetadata: - Type: CompositeResource - Category: Resources Generate_Wiki_Sidebar: Debug: false AlwaysOverwrite: true From 6583d385dbaa130959d50ac0ef791ee1858e398d Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:42:48 +0000 Subject: [PATCH 18/45] Update comment based help and remove code comments --- source/Private/Get-ClassResourcePropertyState2.ps1 | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/source/Private/Get-ClassResourcePropertyState2.ps1 b/source/Private/Get-ClassResourcePropertyState2.ps1 index 81a88273..40186a5d 100644 --- a/source/Private/Get-ClassResourcePropertyState2.ps1 +++ b/source/Private/Get-ClassResourcePropertyState2.ps1 @@ -7,12 +7,11 @@ This function returns the property state value of an DSC class-based resource property. - .PARAMETER Ast - The Abstract Syntax Tree (AST) for class-based DSC resource property. - The passed value must be an AST of the type 'PropertyMemberAst'. + .PARAMETER PropertyInfo + The PropertyInfo of a class-based DSC resource property. .EXAMPLE - Get-ClassResourcePropertyState -Ast { + Get-ClassResourcePropertyState2 -Ast { [DscResource()] class NameOfResource { [DscProperty(Key)] @@ -47,9 +46,6 @@ function Get-ClassResourcePropertyState2 Check for Key first since it it possible to use both Key and Mandatory on a property and in that case we want to return just 'Key'. #> - # Data lives in $PropertyInfo.CustomProperties.NamedArguments - # Need to check attribute type is correct - # TODO: Need to deal with Attribute = False?? $attributeParams = @{ PropertyAttributes = $PropertyInfo.CustomAttributes From fe4a5229cd21cbcd6b26227210ebf88f153ce930 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:43:56 +0000 Subject: [PATCH 19/45] Add empty test files --- tests/unit/private/Get-ClassPropertyCustomAttribute.Tests.ps1 | 0 tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 | 0 tests/unit/private/Get-DscPropertyType.Tests.ps1 | 0 .../unit/private/Test-ClassPropertyDscAttributeArgument.Tests.ps1 | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/unit/private/Get-ClassPropertyCustomAttribute.Tests.ps1 create mode 100644 tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 create mode 100644 tests/unit/private/Get-DscPropertyType.Tests.ps1 create mode 100644 tests/unit/private/Test-ClassPropertyDscAttributeArgument.Tests.ps1 diff --git a/tests/unit/private/Get-ClassPropertyCustomAttribute.Tests.ps1 b/tests/unit/private/Get-ClassPropertyCustomAttribute.Tests.ps1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 b/tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/private/Get-DscPropertyType.Tests.ps1 b/tests/unit/private/Get-DscPropertyType.Tests.ps1 new file mode 100644 index 00000000..e69de29b diff --git a/tests/unit/private/Test-ClassPropertyDscAttributeArgument.Tests.ps1 b/tests/unit/private/Test-ClassPropertyDscAttributeArgument.Tests.ps1 new file mode 100644 index 00000000..e69de29b From faaac4bcbc4ca9c6c9c76f9d2795848633f70b0e Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 09:38:48 +0000 Subject: [PATCH 20/45] Update type to a full type name --- tests/unit/private/New-DscClassResourceWikiPage.Tests.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/private/New-DscClassResourceWikiPage.Tests.ps1 b/tests/unit/private/New-DscClassResourceWikiPage.Tests.ps1 index d4a4b324..06c1dda9 100644 --- a/tests/unit/private/New-DscClassResourceWikiPage.Tests.ps1 +++ b/tests/unit/private/New-DscClassResourceWikiPage.Tests.ps1 @@ -528,7 +528,7 @@ class AzDevOpsProject | **MandatoryProperty** | Required | System.String | MandatoryProperty description. | | | **ProjectId** | Write | System.String | ProjectId description. Second row with text. | | | **ValidateSetProperty** | Write | System.String | | `Up`, `Down` | -| **Reasons** | Read | String[] | Reasons description. | | +| **Reasons** | Read | System.String[] | Reasons description. | | ## Description @@ -709,7 +709,7 @@ class ResourceBase | **Ensure** | Write | System.String | Ensure description. | | | **ProjectId** | Write | System.String | ProjectId description. Second row with text. | | | **ValidateSetProperty** | Write | System.String | | `Up`, `Down` | -| **Reasons** | Read | String[] | Reasons description. | | +| **Reasons** | Read | System.String[] | Reasons description. | | ## Description From 207fdd06ba3ec67cba169b322fe3aeb0d23f0eeb Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 09:39:17 +0000 Subject: [PATCH 21/45] Re-import module every time --- source/Private/New-DscClassResourceWikiPage.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Private/New-DscClassResourceWikiPage.ps1 b/source/Private/New-DscClassResourceWikiPage.ps1 index c7bc2bae..9421fc73 100644 --- a/source/Private/New-DscClassResourceWikiPage.ps1 +++ b/source/Private/New-DscClassResourceWikiPage.ps1 @@ -92,7 +92,7 @@ function New-DscClassResourceWikiPage # Looping through each module file (normally just one). foreach ($builtModuleScriptFile in $builtModuleScriptFiles) { - Import-Module $builtModuleScriptFile.FullName + Import-Module $builtModuleScriptFile.FullName -Force $classesInModule = (Get-Module $builtModuleScriptFile.BaseName).ImplementingAssembly.DefinedTypes | Where-Object { $_.IsClass -and $_.IsPublic } $dscClassesInModule = $classesInModule | Where-Object {'DscResourceAttribute' -in $_.CustomAttributes.AttributeType.Name} From 25c42f8f623b60a166ee4e66a4e15950dccc8526 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 09:39:30 +0000 Subject: [PATCH 22/45] Add Tests --- .../Get-ClassResourceProperty.Tests.ps1 | 613 ++++++++++++++++++ 1 file changed, 613 insertions(+) create mode 100644 tests/unit/private/Get-ClassResourceProperty.Tests.ps1 diff --git a/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 b/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 new file mode 100644 index 00000000..80a47061 --- /dev/null +++ b/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 @@ -0,0 +1,613 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' + +Import-Module $script:moduleName -Force -ErrorAction 'Stop' +#endregion HEADER + +Describe 'Get-ClassResourceProperty' { + InModuleScope $script:moduleName { + Context 'When the resource has a parent class that also has a DSC property' { + BeforeAll { + $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' + $mockSourcePath = Join-Path -Path $TestDrive -ChildPath 'source' + + New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force + New-Item -Path "$mockSourcePath\Classes" -ItemType 'Directory' -Force + + # The class DSC resource in the built module. + $mockBuiltModuleScript = @' +class ResourceBase +{ + hidden [System.String] $NotADscProperty + + [DscProperty()] + [System.String] + $Ensure +} + +[DscResource()] +class MyDscResource : ResourceBase +{ + [MyDscResource] Get() + { + return [MyDscResource] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() {} + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty()] + [ValidateSet('Up', 'Down')] + [System.String[]] $ValidateSetProperty +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockBuiltModulePath\MyClassModule.psm1" -Encoding ascii -Force + + <# + The source file of class DSC resource. This file is not actually + referencing the base class to simplify the tests. + The property ValidateSetProperty does not have a parameter description + to be able to test missing description. + #> + $mockResourceSourceScript = @' +<# + .SYNOPSIS + Resource synopsis. + + .DESCRIPTION + Resource description. + + .PARAMETER ProjectName + ProjectName description. +#> +[DscResource()] +class MyDscResource +{ + [MyDscResource] Get() + { + return [MyDscResource] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() {} + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty()] + [ValidateSet('Up', 'Down')] + [System.String[]] $ValidateSetProperty +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockResourceSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\010.MyDscResource.ps1" -Encoding ascii -Force + + $mockBaseClassSourceScript = @' +<# + .SYNOPSIS + Synopsis for base class. + + .DESCRIPTION + Description for base class + + .PARAMETER Ensure + Ensure description. +#> +class ResourceBase +{ + hidden [System.String] $NotADscProperty + + [DscProperty()] + [System.String] + $Ensure +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockBaseClassSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\001.ResourceBase.ps1" -Encoding ascii -Force + + [System.IO.FileInfo] $mockBuiltModuleFile = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' + Import-Module $mockBuiltModuleFile.FullName -Force + + $classesInModule = (Get-Module $mockBuiltModuleFile.BaseName).ImplementingAssembly.DefinedTypes | Where-Object { $_.IsClass -and $_.IsPublic } + $dscClassInModule = $classesInModule | Where-Object { 'DscResourceAttribute' -in $_.CustomAttributes.AttributeType.Name } + + $dscProperties = $dscClassInModule.GetProperties() | Where-Object { 'DscPropertyAttribute' -in $_.CustomAttributes.AttributeType.Name } + } + + It 'Should return the expected DSC class resource properties' { + $mockGetClassResourcePropertyParameters = @{ + SourcePath = $mockSourcePath + Properties = $dscProperties + } + + $getClassResourcePropertyResult = Get-ClassResourceProperty @mockGetClassResourcePropertyParameters + $getClassResourcePropertyResult | Should -HaveCount 3 + $getClassResourcePropertyResult.Name | Should -Contain 'Ensure' + $getClassResourcePropertyResult.Name | Should -Contain 'ProjectName' + $getClassResourcePropertyResult.Name | Should -Contain 'ValidateSetProperty' + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'Ensure' }) + $ensurePropertyResult.State | Should -Be 'Write' + $ensurePropertyResult.Description | Should -Be 'Ensure description.' + $ensurePropertyResult.DataType | Should -Be 'System.String' + $ensurePropertyResult.IsArray | Should -BeFalse + $ensurePropertyResult.ValueMap | Should -BeNullOrEmpty + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'ProjectName' }) + $ensurePropertyResult.State | Should -Be 'Key' + $ensurePropertyResult.Description | Should -Be 'ProjectName description.' + $ensurePropertyResult.DataType | Should -Be 'System.String' + $ensurePropertyResult.IsArray | Should -BeFalse + $ensurePropertyResult.ValueMap | Should -BeNullOrEmpty + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'ValidateSetProperty' }) + $ensurePropertyResult.State | Should -Be 'Write' + $ensurePropertyResult.Description | Should -BeNullOrEmpty + $ensurePropertyResult.DataType | Should -Be 'System.String[]' + $ensurePropertyResult.IsArray | Should -BeFalse + $ensurePropertyResult.ValueMap | Should -Contain 'Up' + $ensurePropertyResult.ValueMap | Should -Contain 'Down' + } + } + } + + InModuleScope $script:moduleName { + Context 'When the resource has a parent class that does not have a source file (part of another module)' { + BeforeAll { + $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' + $mockSourcePath = Join-Path -Path $TestDrive -ChildPath 'source' + + New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force + New-Item -Path "$mockSourcePath\Classes" -ItemType 'Directory' -Force + + # The class DSC resource in the built module. + $mockBuiltModuleScript = @' +class ResourceBase +{ + hidden [System.String] $NotADscProperty + + [DscProperty()] + [System.String] + $Ensure +} + +[DscResource()] +class MyDscResource : ResourceBase +{ + [MyDscResource] Get() + { + return [MyDscResource] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() {} + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty()] + [ValidateSet('Up', 'Down')] + [System.String[]] $ValidateSetProperty +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockBuiltModulePath\MyClassModule.psm1" -Encoding ascii -Force + + <# + The source file of class DSC resource. This file is not actually + referencing the base class to simplify the tests. + The property ValidateSetProperty does not have a parameter description + to be able to test missing description. + #> + $mockResourceSourceScript = @' +<# +.SYNOPSIS +Resource synopsis. + +.DESCRIPTION +Resource description. + +.PARAMETER ProjectName +ProjectName description. +#> +[DscResource()] +class MyDscResource +{ +[MyDscResource] Get() +{ + return [MyDscResource] $this +} + +[System.Boolean] Test() +{ + return $true +} + +[void] Set() {} + +[DscProperty(Key)] +[System.String] $ProjectName + +[DscProperty()] +[ValidateSet('Up', 'Down')] +[System.String[]] $ValidateSetProperty +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockResourceSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\010.MyDscResource.ps1" -Encoding ascii -Force + + [System.IO.FileInfo] $mockBuiltModuleFile = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' + Import-Module $mockBuiltModuleFile.FullName -Force + + $classesInModule = (Get-Module $mockBuiltModuleFile.BaseName).ImplementingAssembly.DefinedTypes | Where-Object { $_.IsClass -and $_.IsPublic } + $dscClassInModule = $classesInModule | Where-Object { 'DscResourceAttribute' -in $_.CustomAttributes.AttributeType.Name } + + $dscProperties = $dscClassInModule.GetProperties() | Where-Object { 'DscPropertyAttribute' -in $_.CustomAttributes.AttributeType.Name } + } + It 'Should return the expected DSC class resource properties' { + $mockGetClassResourcePropertyParameters = @{ + SourcePath = $mockSourcePath + Properties = $dscProperties + } + + $getClassResourcePropertyResult = Get-ClassResourceProperty @mockGetClassResourcePropertyParameters + $getClassResourcePropertyResult | Should -HaveCount 2 + $getClassResourcePropertyResult.Name | Should -Contain 'ProjectName' + $getClassResourcePropertyResult.Name | Should -Contain 'ValidateSetProperty' + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'ProjectName' }) + $ensurePropertyResult.State | Should -Be 'Key' + $ensurePropertyResult.Description | Should -Be 'ProjectName description.' + $ensurePropertyResult.DataType | Should -Be 'System.String' + $ensurePropertyResult.IsArray | Should -BeFalse + $ensurePropertyResult.ValueMap | Should -BeNullOrEmpty + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'ValidateSetProperty' }) + $ensurePropertyResult.State | Should -Be 'Write' + $ensurePropertyResult.Description | Should -BeNullOrEmpty + $ensurePropertyResult.DataType | Should -Be 'System.String[]' + $ensurePropertyResult.IsArray | Should -BeFalse + $ensurePropertyResult.ValueMap | Should -Contain 'Up' + $ensurePropertyResult.ValueMap | Should -Contain 'Down' + } + } + } + + InModuleScope $script:moduleName { + Context 'When a base class is missing comment-based help' { + BeforeAll { + $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' + $mockSourcePath = Join-Path -Path $TestDrive -ChildPath 'source' + + New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force + New-Item -Path "$mockSourcePath\Classes" -ItemType 'Directory' -Force + + # The class DSC resource in the built module. + $mockBuiltModuleScript = @' +class ResourceBase +{ + hidden [System.String] $NotADscProperty + + [DscProperty()] + [System.String] + $Ensure +} + +[DscResource()] +class MyDscResource : ResourceBase +{ + [MyDscResource] Get() + { + return [MyDscResource] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() {} + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty()] + [System.String] $DescriptionTestProperty +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockBuiltModulePath\MyClassModule.psm1" -Encoding ascii -Force + + <# + The source file of class DSC resource. This file is not actually + referencing the base class to simplify the tests. + + The property DescriptionTestProperty is used to test description + parsing. + #> + $mockResourceSourceScript = @' +<# +.SYNOPSIS + Resource synopsis. + + .DESCRIPTION + Resource description. + + .PARAMETER ProjectName + ProjectName description. + + .PARAMETER DescriptionTestProperty + DescriptionTestProperty description. + + This is a second row with | various tests like double space and vertical bar. +#> +[DscResource()] +class MyDscResource +{ + [MyDscResource] Get() + { + return [MyDscResource] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() {} + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty()] + [System.String] $DescriptionTestProperty +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockResourceSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\010.MyDscResource.ps1" -Encoding ascii -Force + + $mockBaseClassSourceScript = @' +class ResourceBase +{ + hidden [System.String] $NotADscProperty + + [DscProperty()] + [System.String] + $Ensure +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockBaseClassSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\001.ResourceBase.ps1" -Encoding ascii -Force + + [System.IO.FileInfo] $mockBuiltModuleFile = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' + Import-Module $mockBuiltModuleFile.FullName -Force + + $classesInModule = (Get-Module $mockBuiltModuleFile.BaseName).ImplementingAssembly.DefinedTypes | Where-Object { $_.IsClass -and $_.IsPublic } + $dscClassInModule = $classesInModule | Where-Object { 'DscResourceAttribute' -in $_.CustomAttributes.AttributeType.Name } + + $dscProperties = $dscClassInModule.GetProperties() | Where-Object { 'DscPropertyAttribute' -in $_.CustomAttributes.AttributeType.Name } + } + + It 'Should return the expected DSC class resource properties' { + $mockGetClassResourcePropertyParameters = @{ + SourcePath = $mockSourcePath + Properties = $dscProperties + } + + $getClassResourcePropertyResult = Get-ClassResourceProperty @mockGetClassResourcePropertyParameters + $getClassResourcePropertyResult | Should -HaveCount 3 + $getClassResourcePropertyResult.Name | Should -Contain 'Ensure' + $getClassResourcePropertyResult.Name | Should -Contain 'ProjectName' + $getClassResourcePropertyResult.Name | Should -Contain 'DescriptionTestProperty' + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'Ensure' }) + $ensurePropertyResult.State | Should -Be 'Write' + $ensurePropertyResult.Description | Should -BeNullOrEmpty + $ensurePropertyResult.DataType | Should -Be 'System.String' + $ensurePropertyResult.IsArray | Should -BeFalse + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'ProjectName' }) + $ensurePropertyResult.State | Should -Be 'Key' + $ensurePropertyResult.Description | Should -Be 'ProjectName description.' + $ensurePropertyResult.DataType | Should -Be 'System.String' + $ensurePropertyResult.IsArray | Should -BeFalse + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'DescriptionTestProperty' }) + $ensurePropertyResult.State | Should -Be 'Write' + $ensurePropertyResult.Description | Should -BeExactly @' +DescriptionTestProperty description. This is a second row with various tests like double space and vertical bar. +'@ + $ensurePropertyResult.DataType | Should -Be 'System.String' + $ensurePropertyResult.IsArray | Should -BeFalse + } + } + } + + InModuleScope $script:moduleName { + Context 'When two script file names end with similar name' { + BeforeAll { + $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' + $mockSourcePath = Join-Path -Path $TestDrive -ChildPath 'source' + + New-Item -Path $mockBuiltModulePath -ItemType 'Directory' -Force + New-Item -Path "$mockSourcePath\Classes" -ItemType 'Directory' -Force + + # The class DSC resource in the built module. + $mockBuiltModuleScript = @' +class BaseMyDscResource +{ +hidden [System.String] $NotADscProperty + +[DscProperty()] +[System.String] +$Ensure +} + +[DscResource()] +class MyDscResource : BaseMyDscResource +{ +[MyDscResource] Get() +{ + return [MyDscResource] $this +} + +[System.Boolean] Test() +{ + return $true +} + +[void] Set() {} + +[DscProperty(Key)] +[System.String] $ProjectName + +[DscProperty()] +[ValidateSet('Up', 'Down')] +[System.String[]] $ValidateSetProperty +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockBuiltModuleScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockBuiltModulePath\MyClassModule.psm1" -Encoding ascii -Force + + <# + The source file of class DSC resource. This file is not actually + referencing the base class to simplify the tests. + The property ValidateSetProperty does not have a parameter description + to be able to test missing description. + #> + $mockResourceSourceScript = @' +<# +.SYNOPSIS +Resource synopsis. + +.DESCRIPTION +Resource description. + +.PARAMETER ProjectName +ProjectName description. +#> +[DscResource()] +class MyDscResource +{ +[MyDscResource] Get() +{ + return [MyDscResource] $this +} + +[System.Boolean] Test() +{ + return $true +} + +[void] Set() {} + +[DscProperty(Key)] +[System.String] $ProjectName + +[DscProperty()] +[ValidateSet('Up', 'Down')] +[System.String[]] $ValidateSetProperty +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockResourceSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\010.MyDscResource.ps1" -Encoding ascii -Force + + $mockBaseClassSourceScript = @' +<# +.SYNOPSIS +Synopsis for base class. + +.DESCRIPTION +Description for base class + +.PARAMETER Ensure +Ensure description. +#> +class BaseMyDscResource +{ +hidden [System.String] $NotADscProperty + +[DscProperty()] +[System.String] +$Ensure +} +'@ + # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. + $mockBaseClassSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\001.BaseMyDscResource.ps1" -Encoding ascii -Force + + [System.IO.FileInfo] $mockBuiltModuleFile = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' + Import-Module -Name $mockBuiltModuleFile.FullName + + $classesInModule = (Get-Module $mockBuiltModuleFile.BaseName).ImplementingAssembly.DefinedTypes | Where-Object { $_.IsClass -and $_.IsPublic } + $dscClassInModule = $classesInModule | Where-Object { 'DscResourceAttribute' -in $_.CustomAttributes.AttributeType.Name } + + $dscProperties = $dscClassInModule.GetProperties() | Where-Object { 'DscPropertyAttribute' -in $_.CustomAttributes.AttributeType.Name } + } + + It 'Should return the expected DSC class resource properties' { + $mockGetClassResourcePropertyParameters = @{ + SourcePath = $mockSourcePath + Properties = $dscProperties + } + + $getClassResourcePropertyResult = Get-ClassResourceProperty @mockGetClassResourcePropertyParameters + #$getClassResourcePropertyResult | Should -HaveCount 3 + $getClassResourcePropertyResult.Name | Should -Contain 'Ensure' + $getClassResourcePropertyResult.Name | Should -Contain 'ProjectName' + $getClassResourcePropertyResult.Name | Should -Contain 'ValidateSetProperty' + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'Ensure' }) + $ensurePropertyResult.State | Should -Be 'Write' + $ensurePropertyResult.Description | Should -Be 'Ensure description.' + $ensurePropertyResult.DataType | Should -Be 'System.String' + $ensurePropertyResult.IsArray | Should -BeFalse + $ensurePropertyResult.ValueMap | Should -BeNullOrEmpty + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'ProjectName' }) + $ensurePropertyResult.State | Should -Be 'Key' + $ensurePropertyResult.Description | Should -Be 'ProjectName description.' + $ensurePropertyResult.DataType | Should -Be 'System.String' + $ensurePropertyResult.IsArray | Should -BeFalse + $ensurePropertyResult.ValueMap | Should -BeNullOrEmpty + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'ValidateSetProperty' }) + $ensurePropertyResult.State | Should -Be 'Write' + $ensurePropertyResult.Description | Should -BeNullOrEmpty + $ensurePropertyResult.DataType | Should -Be 'System.String[]' + $ensurePropertyResult.IsArray | Should -BeFalse + $ensurePropertyResult.ValueMap | Should -Contain 'Up' + $ensurePropertyResult.ValueMap | Should -Contain 'Down' + } + } + } +} From 72cdebe958f71bf78ac8c226aae75c027a9d5f3f Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 10:01:35 +0000 Subject: [PATCH 23/45] Update tests --- .../private/Get-ClassResourceProperty.Tests.ps1 | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 b/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 index 80a47061..aa2e42f8 100644 --- a/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 +++ b/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 @@ -18,8 +18,8 @@ Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' Import-Module $script:moduleName -Force -ErrorAction 'Stop' #endregion HEADER -Describe 'Get-ClassResourceProperty' { - InModuleScope $script:moduleName { +InModuleScope $script:moduleName { + Describe 'Get-ClassResourceProperty' { Context 'When the resource has a parent class that also has a DSC property' { BeforeAll { $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' @@ -175,9 +175,7 @@ class ResourceBase $ensurePropertyResult.ValueMap | Should -Contain 'Down' } } - } - InModuleScope $script:moduleName { Context 'When the resource has a parent class that does not have a source file (part of another module)' { BeforeAll { $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' @@ -274,6 +272,7 @@ class MyDscResource $dscProperties = $dscClassInModule.GetProperties() | Where-Object { 'DscPropertyAttribute' -in $_.CustomAttributes.AttributeType.Name } } + It 'Should return the expected DSC class resource properties' { $mockGetClassResourcePropertyParameters = @{ SourcePath = $mockSourcePath @@ -301,9 +300,7 @@ class MyDscResource $ensurePropertyResult.ValueMap | Should -Contain 'Down' } } - } - InModuleScope $script:moduleName { Context 'When a base class is missing comment-based help' { BeforeAll { $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' @@ -451,9 +448,7 @@ DescriptionTestProperty description. This is a second row with various tests lik $ensurePropertyResult.IsArray | Should -BeFalse } } - } - InModuleScope $script:moduleName { Context 'When two script file names end with similar name' { BeforeAll { $mockBuiltModulePath = Join-Path -Path $TestDrive -ChildPath 'output\MyClassModule\1.0.0' @@ -566,7 +561,7 @@ $Ensure $mockBaseClassSourceScript | Microsoft.PowerShell.Utility\Out-File -FilePath "$mockSourcePath\Classes\001.BaseMyDscResource.ps1" -Encoding ascii -Force [System.IO.FileInfo] $mockBuiltModuleFile = Join-Path -Path $mockBuiltModulePath -ChildPath 'MyClassModule.psm1' - Import-Module -Name $mockBuiltModuleFile.FullName + Import-Module -Name $mockBuiltModuleFile.FullName -Force $classesInModule = (Get-Module $mockBuiltModuleFile.BaseName).ImplementingAssembly.DefinedTypes | Where-Object { $_.IsClass -and $_.IsPublic } $dscClassInModule = $classesInModule | Where-Object { 'DscResourceAttribute' -in $_.CustomAttributes.AttributeType.Name } From f331829996d593bb30da862a619f7a36e3e2c801 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 10:04:17 +0000 Subject: [PATCH 24/45] Remove debug warning --- source/Private/Get-ClassResourceProperty.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/source/Private/Get-ClassResourceProperty.ps1 b/source/Private/Get-ClassResourceProperty.ps1 index d5e24e6c..92c0ed29 100644 --- a/source/Private/Get-ClassResourceProperty.ps1 +++ b/source/Private/Get-ClassResourceProperty.ps1 @@ -101,7 +101,6 @@ function Get-ClassResourceProperty } $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember - Write-Warning ('Property {0} State = {1}' -f $propertyMember.Name, $propertyAttribute.State) $valueMapValues = $null if ($propertyMember.PropertyType.IsEnum) From 260b6425003af844a6ae1d2e70e623b10b26ae4f Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Fri, 25 Oct 2024 17:23:12 +0100 Subject: [PATCH 25/45] Fix DscClass Doc Generation --- .../Private/Get-ClassResourcePropertyNew.ps1 | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 source/Private/Get-ClassResourcePropertyNew.ps1 diff --git a/source/Private/Get-ClassResourcePropertyNew.ps1 b/source/Private/Get-ClassResourcePropertyNew.ps1 new file mode 100644 index 00000000..70a1027c --- /dev/null +++ b/source/Private/Get-ClassResourcePropertyNew.ps1 @@ -0,0 +1,165 @@ +<# + .SYNOPSIS + Returns DSC class resource properties from the provided class or classes. + + .DESCRIPTION + Returns DSC class resource properties from the provided class or classes. + + .PARAMETER SourcePath + The path to the source folder (in which the child folder 'Classes' exist). + + .PARAMETER BuiltModuleScriptFilePath + The path to the built module script file that contains the class. + + .PARAMETER ClassName + One or more class names to return properties for. + + .EXAMPLE + Get-ClassResourceProperty -ClassName @('myParentClass', 'myClass') -BuiltModuleScriptFilePath '.\output\MyModule\1.0.0\MyModule.psm1' -SourcePath '.\source' + + Returns all DSC class resource properties. +#> +function Get-ClassResourcePropertyNew +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable[]])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $SourcePath, + + # [Parameter(Mandatory = $true)] + # [System.String] + # $BuiltModuleScriptFilePath, + + [Parameter(Mandatory = $true)] + [System.Reflection.PropertyInfo[]] + $Properties + + + ) + + $resourceProperty = [System.Collections.Hashtable[]] @() + + $className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name + + foreach ($currentClassName in $className) + { + #$dscResourceAst = Get-ClassAst -ClassName $currentClassName -ScriptFile $BuiltModuleScriptFilePath + + $classExists = $false + $sourceFilePath = '' + $childPaths = @( + ('Classes/???.{0}.ps1' -f $currentClassName) + ('Classes/{0}.ps1' -f $currentClassName) + ) + + foreach ($childPath in $childPaths) + { + $sourceFilePath = Join-Path -Path $SourcePath -ChildPath $childPath + + if ((Test-Path -Path $sourceFilePath)) + { + $classExists = $true + break + } + } + + <# + Skip if the class's source file does not exist. This can happen if the + class uses a parent class from a different module. + #> + if (-not $classExists) + { + continue + } + + $dscResourceCommentBasedHelp = Get-CommentBasedHelp -Path $sourceFilePath + + # $astFilter = { + # $args[0] -is [System.Management.Automation.Language.PropertyMemberAst] ` + # -and $args[0].Attributes.TypeName.Name -eq 'DscProperty' + # } + + # $propertyMemberAsts = $dscResourceAst.FindAll($astFilter, $true) + $propertyMembers = $Properties | Where-Object { $_.DeclaringType.Name -eq $currentClassName } + + <# + Looping through each resource property to build the resulting + hashtable. Hashtable will be in the format: + + @{ + Name = + State = 'Key' | 'Required' |'Write' | 'Read' + Description = + EmbeddedInstance = 'MSFT_Credential' | $null + DataType = 'System.String' | 'System.String[] | etc. + IsArray = $true | $false + ValueMap = @( | ...) + } + #> + foreach ($propertyMember in $propertyMembers) + { + Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMember.Name, $currentClassName) + + $propertyAttribute = @{ + Name = $propertyMember.Name + DataType = Get-DscPropertyType -PropertyType $propertyMember.PropertyType + + # Always set to null, correct type name is set in DataType. + EmbeddedInstance = $null + + # Always set to $false - correct type name is set in DataType. + IsArray = $false + } + + $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember + + $valueMapValues = $null + if ($propertyMember.PropertyType.IsEnum) + { + $valueMapValues = $propertyMember.PropertyType.GetEnumNames() + } + + $validateSet = Get-ClassPropertyCustomAttribute -Attributes $propertyMember.CustomAttributes -AttributeType 'ValidateSetAttribute' + if ($validateSet) + { + $valueMapValues = $validateSet.ConstructorArguments.Value.Value + } + + if ($valueMapValues) + { + $propertyAttribute.ValueMap = $valueMapValues + } + + if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0) + { + # The key name must be upper-case for it to match the right item in the list of parameters. + $propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMember.Name.ToUpper()] + + if ($propertyDescription) + { + $propertyDescription = Format-Text -Text $propertyDescription -Format @( + 'Remove_Blank_Rows_At_End_Of_String', + 'Remove_Indentation_From_Blank_Rows', + 'Replace_NewLine_With_One_Whitespace', + 'Replace_Vertical_Bar_With_One_Whitespace', + 'Replace_Multiple_Whitespace_With_One', + 'Remove_Whitespace_From_End_Of_String' + ) + } + } + else + { + $propertyDescription = '' + } + + $propertyAttribute.Description = $propertyDescription + + $resourceProperty += $propertyAttribute + } + } + + return $resourceProperty +} From e52cc0b4434c01962eaf242277c46a3b475d1dd2 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 15:00:35 +0000 Subject: [PATCH 26/45] Remove unused function --- .../Private/Get-ClassResourcePropertyNew.ps1 | 165 ------------------ 1 file changed, 165 deletions(-) delete mode 100644 source/Private/Get-ClassResourcePropertyNew.ps1 diff --git a/source/Private/Get-ClassResourcePropertyNew.ps1 b/source/Private/Get-ClassResourcePropertyNew.ps1 deleted file mode 100644 index 70a1027c..00000000 --- a/source/Private/Get-ClassResourcePropertyNew.ps1 +++ /dev/null @@ -1,165 +0,0 @@ -<# - .SYNOPSIS - Returns DSC class resource properties from the provided class or classes. - - .DESCRIPTION - Returns DSC class resource properties from the provided class or classes. - - .PARAMETER SourcePath - The path to the source folder (in which the child folder 'Classes' exist). - - .PARAMETER BuiltModuleScriptFilePath - The path to the built module script file that contains the class. - - .PARAMETER ClassName - One or more class names to return properties for. - - .EXAMPLE - Get-ClassResourceProperty -ClassName @('myParentClass', 'myClass') -BuiltModuleScriptFilePath '.\output\MyModule\1.0.0\MyModule.psm1' -SourcePath '.\source' - - Returns all DSC class resource properties. -#> -function Get-ClassResourcePropertyNew -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable[]])] - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $SourcePath, - - # [Parameter(Mandatory = $true)] - # [System.String] - # $BuiltModuleScriptFilePath, - - [Parameter(Mandatory = $true)] - [System.Reflection.PropertyInfo[]] - $Properties - - - ) - - $resourceProperty = [System.Collections.Hashtable[]] @() - - $className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name - - foreach ($currentClassName in $className) - { - #$dscResourceAst = Get-ClassAst -ClassName $currentClassName -ScriptFile $BuiltModuleScriptFilePath - - $classExists = $false - $sourceFilePath = '' - $childPaths = @( - ('Classes/???.{0}.ps1' -f $currentClassName) - ('Classes/{0}.ps1' -f $currentClassName) - ) - - foreach ($childPath in $childPaths) - { - $sourceFilePath = Join-Path -Path $SourcePath -ChildPath $childPath - - if ((Test-Path -Path $sourceFilePath)) - { - $classExists = $true - break - } - } - - <# - Skip if the class's source file does not exist. This can happen if the - class uses a parent class from a different module. - #> - if (-not $classExists) - { - continue - } - - $dscResourceCommentBasedHelp = Get-CommentBasedHelp -Path $sourceFilePath - - # $astFilter = { - # $args[0] -is [System.Management.Automation.Language.PropertyMemberAst] ` - # -and $args[0].Attributes.TypeName.Name -eq 'DscProperty' - # } - - # $propertyMemberAsts = $dscResourceAst.FindAll($astFilter, $true) - $propertyMembers = $Properties | Where-Object { $_.DeclaringType.Name -eq $currentClassName } - - <# - Looping through each resource property to build the resulting - hashtable. Hashtable will be in the format: - - @{ - Name = - State = 'Key' | 'Required' |'Write' | 'Read' - Description = - EmbeddedInstance = 'MSFT_Credential' | $null - DataType = 'System.String' | 'System.String[] | etc. - IsArray = $true | $false - ValueMap = @( | ...) - } - #> - foreach ($propertyMember in $propertyMembers) - { - Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMember.Name, $currentClassName) - - $propertyAttribute = @{ - Name = $propertyMember.Name - DataType = Get-DscPropertyType -PropertyType $propertyMember.PropertyType - - # Always set to null, correct type name is set in DataType. - EmbeddedInstance = $null - - # Always set to $false - correct type name is set in DataType. - IsArray = $false - } - - $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember - - $valueMapValues = $null - if ($propertyMember.PropertyType.IsEnum) - { - $valueMapValues = $propertyMember.PropertyType.GetEnumNames() - } - - $validateSet = Get-ClassPropertyCustomAttribute -Attributes $propertyMember.CustomAttributes -AttributeType 'ValidateSetAttribute' - if ($validateSet) - { - $valueMapValues = $validateSet.ConstructorArguments.Value.Value - } - - if ($valueMapValues) - { - $propertyAttribute.ValueMap = $valueMapValues - } - - if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0) - { - # The key name must be upper-case for it to match the right item in the list of parameters. - $propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMember.Name.ToUpper()] - - if ($propertyDescription) - { - $propertyDescription = Format-Text -Text $propertyDescription -Format @( - 'Remove_Blank_Rows_At_End_Of_String', - 'Remove_Indentation_From_Blank_Rows', - 'Replace_NewLine_With_One_Whitespace', - 'Replace_Vertical_Bar_With_One_Whitespace', - 'Replace_Multiple_Whitespace_With_One', - 'Remove_Whitespace_From_End_Of_String' - ) - } - } - else - { - $propertyDescription = '' - } - - $propertyAttribute.Description = $propertyDescription - - $resourceProperty += $propertyAttribute - } - } - - return $resourceProperty -} From 436dc7a7798eaf5c1ccf2470416d6fc0e1ec4b63 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 15:16:18 +0000 Subject: [PATCH 27/45] Remove blank lines and fix build warning message --- build.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.yaml b/build.yaml index 01100435..51dc9e8f 100644 --- a/build.yaml +++ b/build.yaml @@ -137,6 +137,16 @@ DscResource.DocGenerator: - '\*(.+?)\*' # Match Italic (asterisk) Publish_GitHub_Wiki_Content: Debug: true + Generate_Markdown_For_DSC_Resources: + MofResourceMetadata: + Type: MofResource + Category: Resources + ClassResourceMetadata: + Type: ClassResource + Category: Resources + CompositeResourceMetadata: + Type: CompositeResource + Category: Resources Generate_Wiki_Sidebar: Debug: false AlwaysOverwrite: true From f2962faf452deb151032b4567f576aead0da5220 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:31:19 +0000 Subject: [PATCH 28/45] Add new helper function --- source/Private/Get-ClassResourceProperty.ps1 | 152 +++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/source/Private/Get-ClassResourceProperty.ps1 b/source/Private/Get-ClassResourceProperty.ps1 index 92c0ed29..e746acbf 100644 --- a/source/Private/Get-ClassResourceProperty.ps1 +++ b/source/Private/Get-ClassResourceProperty.ps1 @@ -149,3 +149,155 @@ function Get-ClassResourceProperty return $resourceProperty } +<# + .SYNOPSIS + Returns DSC class resource properties from the provided PropertyInfo properties. + + .DESCRIPTION + Returns DSC class resource properties from the provided PropertyInfo properties. + + .PARAMETER SourcePath + The path to the source folder (in which the child folder 'Classes' exist). + + .PARAMETER Properties + One or more PropertyInfo objects return properties for. + + .OUTPUTS + System.Collections.Hashtable[] + + .EXAMPLE + Get-ClassResourceProperty -Properties $PropertyInfos -SourcePath '.\source' + + Returns all DSC class resource properties. +#> +function Get-ClassResourceProperty +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable[]])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $SourcePath, + + [Parameter(Mandatory = $true)] + [System.Reflection.PropertyInfo[]] + $Properties + ) + + $resourceProperty = [System.Collections.Hashtable[]] @() + + $className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name + + foreach ($currentClassName in $className) + { + $classExists = $false + $sourceFilePath = '' + $childPaths = @( + ('Classes/???.{0}.ps1' -f $currentClassName) + ('Classes/{0}.ps1' -f $currentClassName) + ) + + foreach ($childPath in $childPaths) + { + $sourceFilePath = Join-Path -Path $SourcePath -ChildPath $childPath + + if ((Test-Path -Path $sourceFilePath)) + { + $classExists = $true + break + } + } + + <# + Skip if the class's source file does not exist. This can happen if the + class uses a parent class from a different module. + #> + if (-not $classExists) + { + continue + } + + $dscResourceCommentBasedHelp = Get-CommentBasedHelp -Path $sourceFilePath + + $propertyMembers = $Properties | Where-Object { $_.DeclaringType.Name -eq $currentClassName } + + <# + Looping through each resource property to build the resulting + hashtable. Hashtable will be in the format: + + @{ + Name = + State = 'Key' | 'Required' |'Write' | 'Read' + Description = + EmbeddedInstance = 'MSFT_Credential' | $null + DataType = 'System.String' | 'System.String[] | etc. + IsArray = $true | $false + ValueMap = @( | ...) + } + #> + foreach ($propertyMember in $propertyMembers) + { + Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMember.Name, $currentClassName) + + $propertyAttribute = @{ + Name = $propertyMember.Name + DataType = Get-DscPropertyType -PropertyType $propertyMember.PropertyType + + # Always set to null, correct type name is set in DataType. + EmbeddedInstance = $null + + # Always set to $false - correct type name is set in DataType. + IsArray = $false + } + + $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember + Write-Warning ('Property {0} State = {1}' -f $propertyMember.Name, $propertyAttribute.State) + + $valueMapValues = $null + if ($propertyMember.PropertyType.IsEnum) + { + $valueMapValues = $propertyMember.PropertyType.GetEnumNames() + } + + $validateSet = Get-ClassPropertyCustomAttribute -Attributes $propertyMember.CustomAttributes -AttributeType 'ValidateSetAttribute' + if ($validateSet) + { + $valueMapValues = $validateSet.ConstructorArguments.Value.Value + } + + if ($valueMapValues) + { + $propertyAttribute.ValueMap = $valueMapValues + } + + if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0) + { + # The key name must be upper-case for it to match the right item in the list of parameters. + $propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMember.Name.ToUpper()] + + if ($propertyDescription) + { + $propertyDescription = Format-Text -Text $propertyDescription -Format @( + 'Remove_Blank_Rows_At_End_Of_String', + 'Remove_Indentation_From_Blank_Rows', + 'Replace_NewLine_With_One_Whitespace', + 'Replace_Vertical_Bar_With_One_Whitespace', + 'Replace_Multiple_Whitespace_With_One', + 'Remove_Whitespace_From_End_Of_String' + ) + } + } + else + { + $propertyDescription = '' + } + + $propertyAttribute.Description = $propertyDescription + + $resourceProperty += $propertyAttribute + } + } + + return $resourceProperty +} From 7897971673db35c4b3dafaa0eb00662b6e61b30f Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Wed, 6 Nov 2024 17:41:20 +0000 Subject: [PATCH 29/45] Use correct docs tasks --- build.yaml | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/build.yaml b/build.yaml index 51dc9e8f..01100435 100644 --- a/build.yaml +++ b/build.yaml @@ -137,16 +137,6 @@ DscResource.DocGenerator: - '\*(.+?)\*' # Match Italic (asterisk) Publish_GitHub_Wiki_Content: Debug: true - Generate_Markdown_For_DSC_Resources: - MofResourceMetadata: - Type: MofResource - Category: Resources - ClassResourceMetadata: - Type: ClassResource - Category: Resources - CompositeResourceMetadata: - Type: CompositeResource - Category: Resources Generate_Wiki_Sidebar: Debug: false AlwaysOverwrite: true From 1d4e5ae9cbfa132e49098ae38bed3871367d2c35 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 10:04:17 +0000 Subject: [PATCH 30/45] Remove debug warning --- source/Private/Get-ClassResourceProperty.ps1 | 152 ++++++++++++++++++- 1 file changed, 151 insertions(+), 1 deletion(-) diff --git a/source/Private/Get-ClassResourceProperty.ps1 b/source/Private/Get-ClassResourceProperty.ps1 index e746acbf..83015d23 100644 --- a/source/Private/Get-ClassResourceProperty.ps1 +++ b/source/Private/Get-ClassResourceProperty.ps1 @@ -252,7 +252,157 @@ function Get-ClassResourceProperty } $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember - Write-Warning ('Property {0} State = {1}' -f $propertyMember.Name, $propertyAttribute.State) + + $valueMapValues = $null + if ($propertyMember.PropertyType.IsEnum) + { + $valueMapValues = $propertyMember.PropertyType.GetEnumNames() + } + + $validateSet = Get-ClassPropertyCustomAttribute -Attributes $propertyMember.CustomAttributes -AttributeType 'ValidateSetAttribute' + if ($validateSet) + { + $valueMapValues = $validateSet.ConstructorArguments.Value.Value + } + + if ($valueMapValues) + { + $propertyAttribute.ValueMap = $valueMapValues + } + + if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0) + { + # The key name must be upper-case for it to match the right item in the list of parameters. + $propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMember.Name.ToUpper()] + + if ($propertyDescription) + { + $propertyDescription = Format-Text -Text $propertyDescription -Format @( + 'Remove_Blank_Rows_At_End_Of_String', + 'Remove_Indentation_From_Blank_Rows', + 'Replace_NewLine_With_One_Whitespace', + 'Replace_Vertical_Bar_With_One_Whitespace', + 'Replace_Multiple_Whitespace_With_One', + 'Remove_Whitespace_From_End_Of_String' + ) + } + } + else + { + $propertyDescription = '' + } + + $propertyAttribute.Description = $propertyDescription + + $resourceProperty += $propertyAttribute + } + } + + return $resourceProperty +} +<# + .SYNOPSIS + Returns DSC class resource properties from the provided PropertyInfo properties. + + .DESCRIPTION + Returns DSC class resource properties from the provided PropertyInfo properties. + + .PARAMETER SourcePath + The path to the source folder (in which the child folder 'Classes' exist). + + .PARAMETER Properties + One or more PropertyInfo objects return properties for. + + .OUTPUTS + System.Collections.Hashtable[] + + .EXAMPLE + Get-ClassResourceProperty -Properties $PropertyInfos -SourcePath '.\source' + + Returns all DSC class resource properties. +#> +function Get-ClassResourceProperty +{ + [CmdletBinding()] + [OutputType([System.Collections.Hashtable[]])] + param + ( + [Parameter(Mandatory = $true)] + [System.String] + $SourcePath, + + [Parameter(Mandatory = $true)] + [System.Reflection.PropertyInfo[]] + $Properties + ) + + $resourceProperty = [System.Collections.Hashtable[]] @() + + $className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name + + foreach ($currentClassName in $className) + { + $classExists = $false + $sourceFilePath = '' + $childPaths = @( + ('Classes/???.{0}.ps1' -f $currentClassName) + ('Classes/{0}.ps1' -f $currentClassName) + ) + + foreach ($childPath in $childPaths) + { + $sourceFilePath = Join-Path -Path $SourcePath -ChildPath $childPath + + if ((Test-Path -Path $sourceFilePath)) + { + $classExists = $true + break + } + } + + <# + Skip if the class's source file does not exist. This can happen if the + class uses a parent class from a different module. + #> + if (-not $classExists) + { + continue + } + + $dscResourceCommentBasedHelp = Get-CommentBasedHelp -Path $sourceFilePath + + $propertyMembers = $Properties | Where-Object { $_.DeclaringType.Name -eq $currentClassName } + + <# + Looping through each resource property to build the resulting + hashtable. Hashtable will be in the format: + + @{ + Name = + State = 'Key' | 'Required' |'Write' | 'Read' + Description = + EmbeddedInstance = 'MSFT_Credential' | $null + DataType = 'System.String' | 'System.String[] | etc. + IsArray = $true | $false + ValueMap = @( | ...) + } + #> + foreach ($propertyMember in $propertyMembers) + { + Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMember.Name, $currentClassName) + + $propertyAttribute = @{ + Name = $propertyMember.Name + DataType = Get-DscPropertyType -PropertyType $propertyMember.PropertyType + + # Always set to null, correct type name is set in DataType. + EmbeddedInstance = $null + + # Always set to $false - correct type name is set in DataType. + IsArray = $false + } + + $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember $valueMapValues = $null if ($propertyMember.PropertyType.IsEnum) From c01999f5294ebf7dce88ebc400b881956fd6e9f6 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 12:42:00 +0000 Subject: [PATCH 31/45] Increase coverage --- .../Get-ClassResourceProperty.Tests.ps1 | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 b/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 index aa2e42f8..dcfefbe2 100644 --- a/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 +++ b/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 @@ -30,6 +30,13 @@ InModuleScope $script:moduleName { # The class DSC resource in the built module. $mockBuiltModuleScript = @' +enum ResourceEnum +{ + Value1 + Value2 + Value3 +} + class ResourceBase { hidden [System.String] $NotADscProperty @@ -60,6 +67,9 @@ class MyDscResource : ResourceBase [DscProperty()] [ValidateSet('Up', 'Down')] [System.String[]] $ValidateSetProperty + + [DscProperty()] + [ResourceEnum] $EnumProperty } '@ # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. @@ -72,6 +82,13 @@ class MyDscResource : ResourceBase to be able to test missing description. #> $mockResourceSourceScript = @' +enum ResourceEnum +{ + Value1 + Value2 + Value3 +} + <# .SYNOPSIS Resource synopsis. @@ -103,6 +120,9 @@ class MyDscResource [DscProperty()] [ValidateSet('Up', 'Down')] [System.String[]] $ValidateSetProperty + + [DscProperty()] + [ResourceEnum] $EnumProperty } '@ # Uses Microsoft.PowerShell.Utility\Out-File to override the stub that is needed for the mocks. @@ -147,10 +167,11 @@ class ResourceBase } $getClassResourcePropertyResult = Get-ClassResourceProperty @mockGetClassResourcePropertyParameters - $getClassResourcePropertyResult | Should -HaveCount 3 + $getClassResourcePropertyResult | Should -HaveCount 4 $getClassResourcePropertyResult.Name | Should -Contain 'Ensure' $getClassResourcePropertyResult.Name | Should -Contain 'ProjectName' $getClassResourcePropertyResult.Name | Should -Contain 'ValidateSetProperty' + $getClassResourcePropertyResult.Name | Should -Contain 'EnumProperty' $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'Ensure' }) $ensurePropertyResult.State | Should -Be 'Write' @@ -173,6 +194,15 @@ class ResourceBase $ensurePropertyResult.IsArray | Should -BeFalse $ensurePropertyResult.ValueMap | Should -Contain 'Up' $ensurePropertyResult.ValueMap | Should -Contain 'Down' + + $ensurePropertyResult = $getClassResourcePropertyResult.Where({ $_.Name -eq 'EnumProperty' }) + $ensurePropertyResult.State | Should -Be 'Write' + $ensurePropertyResult.Description | Should -BeNullOrEmpty + $ensurePropertyResult.DataType | Should -Be 'ResourceEnum' + $ensurePropertyResult.IsArray | Should -BeFalse + $ensurePropertyResult.ValueMap | Should -Contain 'Value1' + $ensurePropertyResult.ValueMap | Should -Contain 'Value2' + $ensurePropertyResult.ValueMap | Should -Contain 'Value3' } } From a0ab9c1acb724cd121dcaf50dd8092c6eae91e7e Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 15:07:22 +0000 Subject: [PATCH 32/45] Add tests --- ...lassPropertyDscAttributeArgument.Tests.ps1 | 256 ++++++++++++++++++ 1 file changed, 256 insertions(+) diff --git a/tests/unit/private/Test-ClassPropertyDscAttributeArgument.Tests.ps1 b/tests/unit/private/Test-ClassPropertyDscAttributeArgument.Tests.ps1 index e69de29b..342b9370 100644 --- a/tests/unit/private/Test-ClassPropertyDscAttributeArgument.Tests.ps1 +++ b/tests/unit/private/Test-ClassPropertyDscAttributeArgument.Tests.ps1 @@ -0,0 +1,256 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' + +Import-Module $script:moduleName -Force -ErrorAction 'Stop' +#endregion HEADER + +InModuleScope $script:moduleName { + Describe 'Test-ClassPropertyDscAttributeArgument' { + Context 'When testing if a property is ''Key''' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] $ProjectName + } + + [AzDevOpsProject].GetProperties() + } + + $mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return $true' { + $mockAttributes = @{ + PropertyAttributes = $mockProperties[0].CustomAttributes + } + + $result = Test-ClassPropertyDscAttributeArgument -IsKey @mockAttributes + + $result | Should -BeTrue + } + + Context 'When testing if a Key property is mandatory' { + It 'Should return $true' { + $mockAttributes = @{ + PropertyAttributes = $mockProperties[0].CustomAttributes + } + + $result = Test-ClassPropertyDscAttributeArgument -IsMandatory @mockAttributes + + $result | Should -BeTrue + } + } + } + + Context 'When testing if a property is ''Write''' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty()] + [System.String] $ProjectId + } + + [AzDevOpsProject].GetProperties() + } + + $mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return $true' { + $mockAttributes = @{ + PropertyAttributes = $mockProperties[1].CustomAttributes + } + + # Makes sure to test the second property (since Key is always needed) + $result = Test-ClassPropertyDscAttributeArgument -IsWrite @mockAttributes + + $result | Should -BeTrue + } + } + + Context 'When testing if a property is ''Mandatory''' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty(Mandatory)] + [System.String] $ProjectId + } + + [AzDevOpsProject].GetProperties() + } + + $mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return $true' { + $mockAttributes = @{ + PropertyAttributes = $mockProperties[1].CustomAttributes + } + + # Makes sure to test the second property (since Key is always needed) + $result = Test-ClassPropertyDscAttributeArgument -IsMandatory @mockAttributes + + $result | Should -BeTrue + } + } + + Context 'When testing if a property is ''Read''' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty(NotConfigurable)] + [System.String] $ProjectId + } + + [AzDevOpsProject].GetProperties() + } + + $mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return $true' { + $mockAttributes = @{ + PropertyAttributes = $mockProperties[1].CustomAttributes + } + + # Makes sure to test the second property (since Key is always needed) + $result = Test-ClassPropertyDscAttributeArgument -IsRead @mockAttributes + + $result | Should -BeTrue + } + } + + Context 'When testing if a property have the expected State property but it does not' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty(NotConfigurable)] + [System.String] $ProjectId + } + + [AzDevOpsProject].GetProperties() + } + + $mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return $false' { + $mockAttributes = @{ + PropertyAttributes = $mockProperties[0].CustomAttributes + } + + # Makes sure to test the second property (since Key is always needed) + $result = Test-ClassPropertyDscAttributeArgument -IsRead @mockAttributes + + $result | Should -BeFalse + } + } + } +} From d7fc8fbf18360dd8e8e75267f6b25b7d9e403719 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 15:58:23 +0000 Subject: [PATCH 33/45] Add tests --- .../private/Get-DscPropertyType.Tests.ps1 | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/tests/unit/private/Get-DscPropertyType.Tests.ps1 b/tests/unit/private/Get-DscPropertyType.Tests.ps1 index e69de29b..5e2ff9ec 100644 --- a/tests/unit/private/Get-DscPropertyType.Tests.ps1 +++ b/tests/unit/private/Get-DscPropertyType.Tests.ps1 @@ -0,0 +1,115 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' + +Import-Module $script:moduleName -Force -ErrorAction 'Stop' +#endregion HEADER + +InModuleScope $script:moduleName { + Describe 'Get-DscPropertyType' { + Context 'When the property type is ''Nullable''' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] + $ProjectName + + [DscProperty(Mandatory)] + [System.String] + $ProjectId + + [DscProperty()] + [Nullable[System.Int32]] + $Index + } + + [AzDevOpsProject].GetProperties() + } + + [System.Reflection.PropertyInfo[]]$mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return the inner type name' { + $result = Get-DscPropertyType -PropertyType $mockProperties[2].PropertyType + + $result | Should -Be 'System.Int32' + } + } + + Context 'When the property type is not ''Nullable''' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] + $ProjectName + + [DscProperty(Mandatory)] + [System.String] + $ProjectId + + [DscProperty()] + [Nullable[System.Int32]] + $Index + } + + [AzDevOpsProject].GetProperties() + } + + [System.Reflection.PropertyInfo[]]$mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return the type name' { + $result = Get-DscPropertyType -PropertyType $mockProperties[1].PropertyType + + $result | Should -Be 'System.String' + } + } + } +} From 61a93568cf772373c2c10ed74e843418d9e3f961 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 16:35:22 +0000 Subject: [PATCH 34/45] Update tests --- ...Get-ClassPropertyCustomAttribute.Tests.ps1 | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/tests/unit/private/Get-ClassPropertyCustomAttribute.Tests.ps1 b/tests/unit/private/Get-ClassPropertyCustomAttribute.Tests.ps1 index e69de29b..47cffa45 100644 --- a/tests/unit/private/Get-ClassPropertyCustomAttribute.Tests.ps1 +++ b/tests/unit/private/Get-ClassPropertyCustomAttribute.Tests.ps1 @@ -0,0 +1,168 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' + +Import-Module $script:moduleName -Force -ErrorAction 'Stop' +#endregion HEADER + +InModuleScope $script:moduleName { + Describe 'Get-ClassPropertyCustomAttribute' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] + $ProjectName + + [ValidateSet('value1', 'value2')] + [System.String] + $ProjectId + + [DscProperty()] + [ValidateRange(0, 1000)] + [Nullable[System.Int32]] + $Index + } + + [AzDevOpsProject].GetProperties() + } + + [System.Reflection.PropertyInfo[]]$mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + Context 'When searching for ''DscAttribute''' { + It 'Should return expected attributes' { + $mockParameters = @{ + Attributes = $mockProperties[0].CustomAttributes + AttributeType = 'DscPropertyAttribute' + } + + [System.Reflection.CustomAttributeData] $result = Get-ClassPropertyCustomAttribute @mockParameters + + $result | Should -Not -BeNullOrEmpty + $result.NamedArguments.MemberName | Should -Be 'Key' + } + + It 'Should return expected attributes' { + $mockParameters = @{ + Attributes = $mockProperties[1].CustomAttributes + AttributeType = 'DscPropertyAttribute' + } + + [System.Reflection.CustomAttributeData] $result = Get-ClassPropertyCustomAttribute @mockParameters + + $result | Should -BeNullOrEmpty + } + + It 'Should return expected attributes' { + $mockParameters = @{ + Attributes = $mockProperties[2].CustomAttributes + AttributeType = 'DscPropertyAttribute' + } + + [System.Reflection.CustomAttributeData] $result = Get-ClassPropertyCustomAttribute @mockParameters + + $result | Should -Not -BeNullOrEmpty + } + } + + Context 'When searching for ''ValidateSetAttribute''' { + It 'Should return expected attributes' { + $mockParameters = @{ + Attributes = $mockProperties[0].CustomAttributes + AttributeType = 'ValidateSetAttribute' + } + + [System.Reflection.CustomAttributeData] $result = Get-ClassPropertyCustomAttribute @mockParameters + + $result | Should -BeNullOrEmpty + } + + It 'Should return expected attributes' { + $mockParameters = @{ + Attributes = $mockProperties[1].CustomAttributes + AttributeType = 'ValidateSetAttribute' + } + + [System.Reflection.CustomAttributeData] $result = Get-ClassPropertyCustomAttribute @mockParameters + + $result | Should -Not -BeNullOrEmpty + } + + It 'Should return expected attributes' { + $mockParameters = @{ + Attributes = $mockProperties[2].CustomAttributes + AttributeType = 'ValidateSetAttribute' + } + + [System.Reflection.CustomAttributeData] $result = Get-ClassPropertyCustomAttribute @mockParameters + + $result | Should -BeNullOrEmpty + } + } + + Context 'When searching for ''ValidateRangeAttribute''' { + It 'Should return expected attributes' { + $mockParameters = @{ + Attributes = $mockProperties[0].CustomAttributes + AttributeType = 'ValidateRangeAttribute' + } + + [System.Reflection.CustomAttributeData] $result = Get-ClassPropertyCustomAttribute @mockParameters + + $result | Should -BeNullOrEmpty + } + + It 'Should return expected attributes' { + $mockParameters = @{ + Attributes = $mockProperties[1].CustomAttributes + AttributeType = 'ValidateRangeAttribute' + } + + [System.Reflection.CustomAttributeData] $result = Get-ClassPropertyCustomAttribute @mockParameters + + $result | Should -BeNullOrEmpty + } + + It 'Should return expected attributes' { + $mockParameters = @{ + Attributes = $mockProperties[2].CustomAttributes + AttributeType = 'ValidateRangeAttribute' + } + + [System.Reflection.CustomAttributeData] $result = Get-ClassPropertyCustomAttribute @mockParameters + + $result | Should -Not -BeNullOrEmpty + } + } + } +} From d36ab9920b2ff2786aed549f88c16495bd0e327e Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 16:41:25 +0000 Subject: [PATCH 35/45] Update example --- .../Get-ClassResourcePropertyState2.ps1 | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/source/Private/Get-ClassResourcePropertyState2.ps1 b/source/Private/Get-ClassResourcePropertyState2.ps1 index 40186a5d..1d763922 100644 --- a/source/Private/Get-ClassResourcePropertyState2.ps1 +++ b/source/Private/Get-ClassResourcePropertyState2.ps1 @@ -11,23 +11,7 @@ The PropertyInfo of a class-based DSC resource property. .EXAMPLE - Get-ClassResourcePropertyState2 -Ast { - [DscResource()] - class NameOfResource { - [DscProperty(Key)] - [string] $KeyName - - [NameOfResource] Get() { - return $this - } - - [void] Set() {} - - [bool] Test() { - return $true - } - } - }.Ast.Find({$args[0] -is [System.Management.Automation.Language.PropertyMemberAst]}, $false) + Get-ClassResourcePropertyState2 -PropertyInfo $properties Returns the property state for the property 'KeyName'. #> From e1006e77feb4e3d041a55fd6bcf241a68fe349bd Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 16:41:31 +0000 Subject: [PATCH 36/45] Update tests --- .../Get-ClassResourcePropertyState2.Tests.ps1 | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) diff --git a/tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 b/tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 index e69de29b..bd03ce2f 100644 --- a/tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 +++ b/tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 @@ -0,0 +1,183 @@ +#region HEADER +$script:projectPath = "$PSScriptRoot\..\..\.." | Convert-Path +$script:projectName = (Get-ChildItem -Path "$script:projectPath\*\*.psd1" | Where-Object -FilterScript { + ($_.Directory.Name -match 'source|src' -or $_.Directory.Name -eq $_.BaseName) -and + $(try + { + Test-ModuleManifest -Path $_.FullName -ErrorAction Stop + } + catch + { + $false + }) + }).BaseName + +$script:moduleName = Get-Module -Name $script:projectName -ListAvailable | Select-Object -First 1 +Remove-Module -Name $script:moduleName -Force -ErrorAction 'SilentlyContinue' + +Import-Module $script:moduleName -Force -ErrorAction 'Stop' +#endregion HEADER + +InModuleScope $script:moduleName { + Describe 'Get-ClassResourcePropertyState' { + Context 'When a property have the named attribute argument ''Key''' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] $ProjectName + } + + [AzDevOpsProject].GetProperties() + } + + $mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return the state as ''Key''' { + $result = Get-ClassResourcePropertyState2 -PropertyInfo $mockProperties[0] -Verbose + + $result | Should -Be 'Key' + } + } + + Context 'When a property have no named attribute argument' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty()] + [System.String] $ProjectId + } + + [AzDevOpsProject].GetProperties() + } + + $mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return the state as ''Write''' { + # Makes sure to test the second property (since Key is always needed) + $result = Get-ClassResourcePropertyState2 -PropertyInfo $mockProperties[1] -Verbose + + $result | Should -Be 'Write' + } + } + + Context 'When a property have the named attribute argument ''Mandatory''' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty(Mandatory)] + [System.String] $ProjectId + } + + [AzDevOpsProject].GetProperties() + } + + $mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return the state as ''Required''' { + # Makes sure to test the second property (since Key is always needed) + $result = Get-ClassResourcePropertyState2 -PropertyInfo $mockProperties[1] -Verbose + + $result | Should -Be 'Required' + } + } + + Context 'When a property have the named attribute argument ''NotConfigurable''' { + BeforeAll { + $mockClassBasedScript = { + [DscResource()] + class AzDevOpsProject + { + [AzDevOpsProject] Get() + { + return [AzDevOpsProject] $this + } + + [System.Boolean] Test() + { + return $true + } + + [void] Set() + { + } + + [DscProperty(Key)] + [System.String] $ProjectName + + [DscProperty(NotConfigurable)] + [System.String] $ProjectId + } + + [AzDevOpsProject].GetProperties() + } + + $mockProperties = $mockClassBasedScript.InvokeReturnAsIs() + } + + It 'Should return the state as ''Read''' { + # Makes sure to test the second property (since Key is always needed) + $result = Get-ClassResourcePropertyState2 -PropertyInfo $mockProperties[1] -Verbose + + $result | Should -Be 'Read' + } + } + } +} From 17c5160b097a7f496984f29865aeb1ed3d339688 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 16:45:53 +0000 Subject: [PATCH 37/45] Update Changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 062f4cff..41028a20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 filename. The task will convert standard hyphens to spaces and Unicode hyphens to standard hyphens before comparison. The task can be controlled by parameter `RemoveTopLevelHeader` in the task, which defaults to `$true`. +- Added Helper functions as part of [#163] (https://github.com/dsccommunity/DscResource.DocGenerator/pull/163). + - `Get-ClassPropertyCustomAttribute` + - `Get-ClassResourcePropertyState2` + - `Get-DscPropertyType` + - `Test-ClassPropertyDscAttributeArgument` ### Changed From dce4916e5e14e373fb4f9564d5f3e8384a3ad8d7 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 17:20:35 +0000 Subject: [PATCH 38/45] Fix merge failure --- source/Private/Get-ClassResourceProperty.ps1 | 302 ------------------- 1 file changed, 302 deletions(-) diff --git a/source/Private/Get-ClassResourceProperty.ps1 b/source/Private/Get-ClassResourceProperty.ps1 index 83015d23..92c0ed29 100644 --- a/source/Private/Get-ClassResourceProperty.ps1 +++ b/source/Private/Get-ClassResourceProperty.ps1 @@ -149,305 +149,3 @@ function Get-ClassResourceProperty return $resourceProperty } -<# - .SYNOPSIS - Returns DSC class resource properties from the provided PropertyInfo properties. - - .DESCRIPTION - Returns DSC class resource properties from the provided PropertyInfo properties. - - .PARAMETER SourcePath - The path to the source folder (in which the child folder 'Classes' exist). - - .PARAMETER Properties - One or more PropertyInfo objects return properties for. - - .OUTPUTS - System.Collections.Hashtable[] - - .EXAMPLE - Get-ClassResourceProperty -Properties $PropertyInfos -SourcePath '.\source' - - Returns all DSC class resource properties. -#> -function Get-ClassResourceProperty -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable[]])] - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $SourcePath, - - [Parameter(Mandatory = $true)] - [System.Reflection.PropertyInfo[]] - $Properties - ) - - $resourceProperty = [System.Collections.Hashtable[]] @() - - $className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name - - foreach ($currentClassName in $className) - { - $classExists = $false - $sourceFilePath = '' - $childPaths = @( - ('Classes/???.{0}.ps1' -f $currentClassName) - ('Classes/{0}.ps1' -f $currentClassName) - ) - - foreach ($childPath in $childPaths) - { - $sourceFilePath = Join-Path -Path $SourcePath -ChildPath $childPath - - if ((Test-Path -Path $sourceFilePath)) - { - $classExists = $true - break - } - } - - <# - Skip if the class's source file does not exist. This can happen if the - class uses a parent class from a different module. - #> - if (-not $classExists) - { - continue - } - - $dscResourceCommentBasedHelp = Get-CommentBasedHelp -Path $sourceFilePath - - $propertyMembers = $Properties | Where-Object { $_.DeclaringType.Name -eq $currentClassName } - - <# - Looping through each resource property to build the resulting - hashtable. Hashtable will be in the format: - - @{ - Name = - State = 'Key' | 'Required' |'Write' | 'Read' - Description = - EmbeddedInstance = 'MSFT_Credential' | $null - DataType = 'System.String' | 'System.String[] | etc. - IsArray = $true | $false - ValueMap = @( | ...) - } - #> - foreach ($propertyMember in $propertyMembers) - { - Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMember.Name, $currentClassName) - - $propertyAttribute = @{ - Name = $propertyMember.Name - DataType = Get-DscPropertyType -PropertyType $propertyMember.PropertyType - - # Always set to null, correct type name is set in DataType. - EmbeddedInstance = $null - - # Always set to $false - correct type name is set in DataType. - IsArray = $false - } - - $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember - - $valueMapValues = $null - if ($propertyMember.PropertyType.IsEnum) - { - $valueMapValues = $propertyMember.PropertyType.GetEnumNames() - } - - $validateSet = Get-ClassPropertyCustomAttribute -Attributes $propertyMember.CustomAttributes -AttributeType 'ValidateSetAttribute' - if ($validateSet) - { - $valueMapValues = $validateSet.ConstructorArguments.Value.Value - } - - if ($valueMapValues) - { - $propertyAttribute.ValueMap = $valueMapValues - } - - if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0) - { - # The key name must be upper-case for it to match the right item in the list of parameters. - $propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMember.Name.ToUpper()] - - if ($propertyDescription) - { - $propertyDescription = Format-Text -Text $propertyDescription -Format @( - 'Remove_Blank_Rows_At_End_Of_String', - 'Remove_Indentation_From_Blank_Rows', - 'Replace_NewLine_With_One_Whitespace', - 'Replace_Vertical_Bar_With_One_Whitespace', - 'Replace_Multiple_Whitespace_With_One', - 'Remove_Whitespace_From_End_Of_String' - ) - } - } - else - { - $propertyDescription = '' - } - - $propertyAttribute.Description = $propertyDescription - - $resourceProperty += $propertyAttribute - } - } - - return $resourceProperty -} -<# - .SYNOPSIS - Returns DSC class resource properties from the provided PropertyInfo properties. - - .DESCRIPTION - Returns DSC class resource properties from the provided PropertyInfo properties. - - .PARAMETER SourcePath - The path to the source folder (in which the child folder 'Classes' exist). - - .PARAMETER Properties - One or more PropertyInfo objects return properties for. - - .OUTPUTS - System.Collections.Hashtable[] - - .EXAMPLE - Get-ClassResourceProperty -Properties $PropertyInfos -SourcePath '.\source' - - Returns all DSC class resource properties. -#> -function Get-ClassResourceProperty -{ - [CmdletBinding()] - [OutputType([System.Collections.Hashtable[]])] - param - ( - [Parameter(Mandatory = $true)] - [System.String] - $SourcePath, - - [Parameter(Mandatory = $true)] - [System.Reflection.PropertyInfo[]] - $Properties - ) - - $resourceProperty = [System.Collections.Hashtable[]] @() - - $className = ($dscProperties | Select-Object -Unique DeclaringType).DeclaringType.Name - - foreach ($currentClassName in $className) - { - $classExists = $false - $sourceFilePath = '' - $childPaths = @( - ('Classes/???.{0}.ps1' -f $currentClassName) - ('Classes/{0}.ps1' -f $currentClassName) - ) - - foreach ($childPath in $childPaths) - { - $sourceFilePath = Join-Path -Path $SourcePath -ChildPath $childPath - - if ((Test-Path -Path $sourceFilePath)) - { - $classExists = $true - break - } - } - - <# - Skip if the class's source file does not exist. This can happen if the - class uses a parent class from a different module. - #> - if (-not $classExists) - { - continue - } - - $dscResourceCommentBasedHelp = Get-CommentBasedHelp -Path $sourceFilePath - - $propertyMembers = $Properties | Where-Object { $_.DeclaringType.Name -eq $currentClassName } - - <# - Looping through each resource property to build the resulting - hashtable. Hashtable will be in the format: - - @{ - Name = - State = 'Key' | 'Required' |'Write' | 'Read' - Description = - EmbeddedInstance = 'MSFT_Credential' | $null - DataType = 'System.String' | 'System.String[] | etc. - IsArray = $true | $false - ValueMap = @( | ...) - } - #> - foreach ($propertyMember in $propertyMembers) - { - Write-Verbose -Message ($script:localizedData.FoundClassResourcePropertyMessage -f $propertyMember.Name, $currentClassName) - - $propertyAttribute = @{ - Name = $propertyMember.Name - DataType = Get-DscPropertyType -PropertyType $propertyMember.PropertyType - - # Always set to null, correct type name is set in DataType. - EmbeddedInstance = $null - - # Always set to $false - correct type name is set in DataType. - IsArray = $false - } - - $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember - - $valueMapValues = $null - if ($propertyMember.PropertyType.IsEnum) - { - $valueMapValues = $propertyMember.PropertyType.GetEnumNames() - } - - $validateSet = Get-ClassPropertyCustomAttribute -Attributes $propertyMember.CustomAttributes -AttributeType 'ValidateSetAttribute' - if ($validateSet) - { - $valueMapValues = $validateSet.ConstructorArguments.Value.Value - } - - if ($valueMapValues) - { - $propertyAttribute.ValueMap = $valueMapValues - } - - if ($dscResourceCommentBasedHelp -and $dscResourceCommentBasedHelp.Parameters.Count -gt 0) - { - # The key name must be upper-case for it to match the right item in the list of parameters. - $propertyDescription = $dscResourceCommentBasedHelp.Parameters[$propertyMember.Name.ToUpper()] - - if ($propertyDescription) - { - $propertyDescription = Format-Text -Text $propertyDescription -Format @( - 'Remove_Blank_Rows_At_End_Of_String', - 'Remove_Indentation_From_Blank_Rows', - 'Replace_NewLine_With_One_Whitespace', - 'Replace_Vertical_Bar_With_One_Whitespace', - 'Replace_Multiple_Whitespace_With_One', - 'Remove_Whitespace_From_End_Of_String' - ) - } - } - else - { - $propertyDescription = '' - } - - $propertyAttribute.Description = $propertyDescription - - $resourceProperty += $propertyAttribute - } - } - - return $resourceProperty -} From 192445af934d2b5baa1667d31d5b27b38b371fe9 Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 17:20:48 +0000 Subject: [PATCH 39/45] Remove comment --- tests/unit/private/Get-ClassResourceProperty.Tests.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 b/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 index dcfefbe2..349e9e44 100644 --- a/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 +++ b/tests/unit/private/Get-ClassResourceProperty.Tests.ps1 @@ -606,7 +606,7 @@ $Ensure } $getClassResourcePropertyResult = Get-ClassResourceProperty @mockGetClassResourcePropertyParameters - #$getClassResourcePropertyResult | Should -HaveCount 3 + $getClassResourcePropertyResult | Should -HaveCount 3 $getClassResourcePropertyResult.Name | Should -Contain 'Ensure' $getClassResourcePropertyResult.Name | Should -Contain 'ProjectName' $getClassResourcePropertyResult.Name | Should -Contain 'ValidateSetProperty' From 1144d26a22f0827523823de7d8876a2d18d7f5ff Mon Sep 17 00:00:00 2001 From: Daniel Hughes Date: Thu, 7 Nov 2024 17:25:11 +0000 Subject: [PATCH 40/45] Undo config change --- build.yaml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.yaml b/build.yaml index 01100435..fd691f7f 100644 --- a/build.yaml +++ b/build.yaml @@ -137,6 +137,16 @@ DscResource.DocGenerator: - '\*(.+?)\*' # Match Italic (asterisk) Publish_GitHub_Wiki_Content: Debug: true + Generate_Wiki_Content: + MofResourceMetadata: + Type: MofResource + Category: Resources + ClassResourceMetadata: + Type: ClassResource + Category: Resources + CompositeResourceMetadata: + Type: CompositeResource + Category: Resources Generate_Wiki_Sidebar: Debug: false AlwaysOverwrite: true From ec32d719555620181fd9918ae4847d7762acf90c Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Sun, 17 Nov 2024 13:20:56 +0000 Subject: [PATCH 41/45] Re-add all docs tasks --- build.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.yaml b/build.yaml index fd691f7f..63bdd4b3 100644 --- a/build.yaml +++ b/build.yaml @@ -39,7 +39,10 @@ BuildWorkflow: docs: - Generate_Conceptual_Help - Generate_Wiki_Content + - Generate_Markdown_For_Public_Commands + - Generate_External_Help_File_For_Public_Commands - Generate_Wiki_Sidebar + - Clean_Markdown_Of_Public_Commands - Clean_Markdown_Metadata - Package_Wiki_Content From b56de0f38267059259c4b2249b2d3612adc2e06b Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Sun, 17 Nov 2024 13:31:03 +0000 Subject: [PATCH 42/45] Remove config warning, remove tasks run by Generate_Wiki_Content --- build.yaml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/build.yaml b/build.yaml index 63bdd4b3..51dc9e8f 100644 --- a/build.yaml +++ b/build.yaml @@ -39,10 +39,7 @@ BuildWorkflow: docs: - Generate_Conceptual_Help - Generate_Wiki_Content - - Generate_Markdown_For_Public_Commands - - Generate_External_Help_File_For_Public_Commands - Generate_Wiki_Sidebar - - Clean_Markdown_Of_Public_Commands - Clean_Markdown_Metadata - Package_Wiki_Content @@ -140,7 +137,7 @@ DscResource.DocGenerator: - '\*(.+?)\*' # Match Italic (asterisk) Publish_GitHub_Wiki_Content: Debug: true - Generate_Wiki_Content: + Generate_Markdown_For_DSC_Resources: MofResourceMetadata: Type: MofResource Category: Resources From fb5aa9f5f70735e197f797d0c3f190097c57fe73 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Sun, 17 Nov 2024 14:39:08 +0000 Subject: [PATCH 43/45] Rename Get-ClassResourcePropertyState2 to Get-ClassResourcePropertyType --- CHANGELOG.md | 2 +- ...1 => Get-ClassDscResourcePropertyType.ps1} | 20 +++++++++---------- source/Private/Get-ClassResourceProperty.ps1 | 2 +- ...> Get-ClassResourcePropertyType.Tests.ps1} | 10 +++++----- 4 files changed, 17 insertions(+), 17 deletions(-) rename source/Private/{Get-ClassResourcePropertyState2.ps1 => Get-ClassDscResourcePropertyType.ps1} (67%) rename tests/unit/private/{Get-ClassResourcePropertyState2.Tests.ps1 => Get-ClassResourcePropertyType.Tests.ps1} (92%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41028a20..58eec295 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 by parameter `RemoveTopLevelHeader` in the task, which defaults to `$true`. - Added Helper functions as part of [#163] (https://github.com/dsccommunity/DscResource.DocGenerator/pull/163). - `Get-ClassPropertyCustomAttribute` - - `Get-ClassResourcePropertyState2` + - `Get-ClassResourcePropertyType` - `Get-DscPropertyType` - `Test-ClassPropertyDscAttributeArgument` diff --git a/source/Private/Get-ClassResourcePropertyState2.ps1 b/source/Private/Get-ClassDscResourcePropertyType.ps1 similarity index 67% rename from source/Private/Get-ClassResourcePropertyState2.ps1 rename to source/Private/Get-ClassDscResourcePropertyType.ps1 index 1d763922..789a6dad 100644 --- a/source/Private/Get-ClassResourcePropertyState2.ps1 +++ b/source/Private/Get-ClassDscResourcePropertyType.ps1 @@ -1,21 +1,21 @@ <# .SYNOPSIS - This function returns the property state value of an class-based DSC + This function returns the property type of a class-based DSC resource property. .DESCRIPTION - This function returns the property state value of an DSC class-based + This function returns the property type value of a DSC class-based resource property. .PARAMETER PropertyInfo - The PropertyInfo of a class-based DSC resource property. + The PropertyInfo object of a class-based DSC resource property. .EXAMPLE - Get-ClassResourcePropertyState2 -PropertyInfo $properties + Get-ClassResourcePropertyType -PropertyInfo $properties Returns the property state for the property 'KeyName'. #> -function Get-ClassResourcePropertyState2 +function Get-ClassResourcePropertyType { [CmdletBinding()] [OutputType([System.String])] @@ -37,20 +37,20 @@ function Get-ClassResourcePropertyState2 if ((Test-ClassPropertyDscAttributeArgument -IsKey @attributeParams)) { - $propertyState = 'Key' + $propertyType = 'Key' } elseif ((Test-ClassPropertyDscAttributeArgument -IsMandatory @attributeParams)) { - $propertyState = 'Required' + $propertyType = 'Required' } elseif ((Test-ClassPropertyDscAttributeArgument -IsRead @attributeParams)) { - $propertyState = 'Read' + $propertyType = 'Read' } elseif ((Test-ClassPropertyDscAttributeArgument -IsWrite @attributeParams)) { - $propertyState = 'Write' + $propertyType = 'Write' } - return $propertyState + return $propertyType } diff --git a/source/Private/Get-ClassResourceProperty.ps1 b/source/Private/Get-ClassResourceProperty.ps1 index 92c0ed29..40747b7d 100644 --- a/source/Private/Get-ClassResourceProperty.ps1 +++ b/source/Private/Get-ClassResourceProperty.ps1 @@ -100,7 +100,7 @@ function Get-ClassResourceProperty IsArray = $false } - $propertyAttribute.State = Get-ClassResourcePropertyState2 -PropertyInfo $propertyMember + $propertyAttribute.State = Get-ClassResourcePropertyType -PropertyInfo $propertyMember $valueMapValues = $null if ($propertyMember.PropertyType.IsEnum) diff --git a/tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 b/tests/unit/private/Get-ClassResourcePropertyType.Tests.ps1 similarity index 92% rename from tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 rename to tests/unit/private/Get-ClassResourcePropertyType.Tests.ps1 index bd03ce2f..e1c65de6 100644 --- a/tests/unit/private/Get-ClassResourcePropertyState2.Tests.ps1 +++ b/tests/unit/private/Get-ClassResourcePropertyType.Tests.ps1 @@ -19,7 +19,7 @@ Import-Module $script:moduleName -Force -ErrorAction 'Stop' #endregion HEADER InModuleScope $script:moduleName { - Describe 'Get-ClassResourcePropertyState' { + Describe 'Get-ClassResourcePropertyType' { Context 'When a property have the named attribute argument ''Key''' { BeforeAll { $mockClassBasedScript = { @@ -51,7 +51,7 @@ InModuleScope $script:moduleName { } It 'Should return the state as ''Key''' { - $result = Get-ClassResourcePropertyState2 -PropertyInfo $mockProperties[0] -Verbose + $result = Get-ClassResourcePropertyType -PropertyInfo $mockProperties[0] -Verbose $result | Should -Be 'Key' } @@ -92,7 +92,7 @@ InModuleScope $script:moduleName { It 'Should return the state as ''Write''' { # Makes sure to test the second property (since Key is always needed) - $result = Get-ClassResourcePropertyState2 -PropertyInfo $mockProperties[1] -Verbose + $result = Get-ClassResourcePropertyType -PropertyInfo $mockProperties[1] -Verbose $result | Should -Be 'Write' } @@ -133,7 +133,7 @@ InModuleScope $script:moduleName { It 'Should return the state as ''Required''' { # Makes sure to test the second property (since Key is always needed) - $result = Get-ClassResourcePropertyState2 -PropertyInfo $mockProperties[1] -Verbose + $result = Get-ClassResourcePropertyType -PropertyInfo $mockProperties[1] -Verbose $result | Should -Be 'Required' } @@ -174,7 +174,7 @@ InModuleScope $script:moduleName { It 'Should return the state as ''Read''' { # Makes sure to test the second property (since Key is always needed) - $result = Get-ClassResourcePropertyState2 -PropertyInfo $mockProperties[1] -Verbose + $result = Get-ClassResourcePropertyType -PropertyInfo $mockProperties[1] -Verbose $result | Should -Be 'Read' } From ce3e15f96cb52a2f2df26bd81dbe5057e12a347d Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Sun, 17 Nov 2024 14:54:20 +0000 Subject: [PATCH 44/45] Match filename to function name --- ...ResourcePropertyType.ps1 => Get-ClassResourcePropertyType.ps1} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename source/Private/{Get-ClassDscResourcePropertyType.ps1 => Get-ClassResourcePropertyType.ps1} (100%) diff --git a/source/Private/Get-ClassDscResourcePropertyType.ps1 b/source/Private/Get-ClassResourcePropertyType.ps1 similarity index 100% rename from source/Private/Get-ClassDscResourcePropertyType.ps1 rename to source/Private/Get-ClassResourcePropertyType.ps1 From 22101f6b16146ca771f484df766cd18e5e354ee6 Mon Sep 17 00:00:00 2001 From: Dan Hughes <2237515+dan-hughes@users.noreply.github.com> Date: Sun, 17 Nov 2024 15:46:35 +0000 Subject: [PATCH 45/45] Rename function again --- CHANGELOG.md | 2 +- source/Private/Get-ClassResourceProperty.ps1 | 2 +- ...tyType.ps1 => Get-DscResourceAttributeProperty.ps1} | 4 ++-- ....ps1 => Get-DscResourceAttributeProperty.Tests.ps1} | 10 +++++----- 4 files changed, 9 insertions(+), 9 deletions(-) rename source/Private/{Get-ClassResourcePropertyType.ps1 => Get-DscResourceAttributeProperty.ps1} (92%) rename tests/unit/private/{Get-ClassResourcePropertyType.Tests.ps1 => Get-DscResourceAttributeProperty.Tests.ps1} (92%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58eec295..18ea1827 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 by parameter `RemoveTopLevelHeader` in the task, which defaults to `$true`. - Added Helper functions as part of [#163] (https://github.com/dsccommunity/DscResource.DocGenerator/pull/163). - `Get-ClassPropertyCustomAttribute` - - `Get-ClassResourcePropertyType` + - `Get-DscResourceAttributeProperty` - `Get-DscPropertyType` - `Test-ClassPropertyDscAttributeArgument` diff --git a/source/Private/Get-ClassResourceProperty.ps1 b/source/Private/Get-ClassResourceProperty.ps1 index 40747b7d..98952bb1 100644 --- a/source/Private/Get-ClassResourceProperty.ps1 +++ b/source/Private/Get-ClassResourceProperty.ps1 @@ -100,7 +100,7 @@ function Get-ClassResourceProperty IsArray = $false } - $propertyAttribute.State = Get-ClassResourcePropertyType -PropertyInfo $propertyMember + $propertyAttribute.State = Get-DscResourceAttributeProperty -PropertyInfo $propertyMember $valueMapValues = $null if ($propertyMember.PropertyType.IsEnum) diff --git a/source/Private/Get-ClassResourcePropertyType.ps1 b/source/Private/Get-DscResourceAttributeProperty.ps1 similarity index 92% rename from source/Private/Get-ClassResourcePropertyType.ps1 rename to source/Private/Get-DscResourceAttributeProperty.ps1 index 789a6dad..f8af6ae1 100644 --- a/source/Private/Get-ClassResourcePropertyType.ps1 +++ b/source/Private/Get-DscResourceAttributeProperty.ps1 @@ -11,11 +11,11 @@ The PropertyInfo object of a class-based DSC resource property. .EXAMPLE - Get-ClassResourcePropertyType -PropertyInfo $properties + Get-DscResourceAttributeProperty -PropertyInfo $properties Returns the property state for the property 'KeyName'. #> -function Get-ClassResourcePropertyType +function Get-DscResourceAttributeProperty { [CmdletBinding()] [OutputType([System.String])] diff --git a/tests/unit/private/Get-ClassResourcePropertyType.Tests.ps1 b/tests/unit/private/Get-DscResourceAttributeProperty.Tests.ps1 similarity index 92% rename from tests/unit/private/Get-ClassResourcePropertyType.Tests.ps1 rename to tests/unit/private/Get-DscResourceAttributeProperty.Tests.ps1 index e1c65de6..a67b5a1f 100644 --- a/tests/unit/private/Get-ClassResourcePropertyType.Tests.ps1 +++ b/tests/unit/private/Get-DscResourceAttributeProperty.Tests.ps1 @@ -19,7 +19,7 @@ Import-Module $script:moduleName -Force -ErrorAction 'Stop' #endregion HEADER InModuleScope $script:moduleName { - Describe 'Get-ClassResourcePropertyType' { + Describe 'Get-DscResourceAttributeProperty' { Context 'When a property have the named attribute argument ''Key''' { BeforeAll { $mockClassBasedScript = { @@ -51,7 +51,7 @@ InModuleScope $script:moduleName { } It 'Should return the state as ''Key''' { - $result = Get-ClassResourcePropertyType -PropertyInfo $mockProperties[0] -Verbose + $result = Get-DscResourceAttributeProperty -PropertyInfo $mockProperties[0] -Verbose $result | Should -Be 'Key' } @@ -92,7 +92,7 @@ InModuleScope $script:moduleName { It 'Should return the state as ''Write''' { # Makes sure to test the second property (since Key is always needed) - $result = Get-ClassResourcePropertyType -PropertyInfo $mockProperties[1] -Verbose + $result = Get-DscResourceAttributeProperty -PropertyInfo $mockProperties[1] -Verbose $result | Should -Be 'Write' } @@ -133,7 +133,7 @@ InModuleScope $script:moduleName { It 'Should return the state as ''Required''' { # Makes sure to test the second property (since Key is always needed) - $result = Get-ClassResourcePropertyType -PropertyInfo $mockProperties[1] -Verbose + $result = Get-DscResourceAttributeProperty -PropertyInfo $mockProperties[1] -Verbose $result | Should -Be 'Required' } @@ -174,7 +174,7 @@ InModuleScope $script:moduleName { It 'Should return the state as ''Read''' { # Makes sure to test the second property (since Key is always needed) - $result = Get-ClassResourcePropertyType -PropertyInfo $mockProperties[1] -Verbose + $result = Get-DscResourceAttributeProperty -PropertyInfo $mockProperties[1] -Verbose $result | Should -Be 'Read' }