Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Get-ClassResourceAst: New command proposal #18

Open
johlju opened this issue Nov 17, 2024 · 0 comments
Open

Get-ClassResourceAst: New command proposal #18

johlju opened this issue Nov 17, 2024 · 0 comments

Comments

@johlju
Copy link
Member

johlju commented Nov 17, 2024

Command proposal

<#
    .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
}

Tests:

#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'
            }
        }
    }
}

Proposed parameters

Parameter Mandatory Data type Description Default value Allowed values
  • | Yes | String | Detailed description | None | None

Special considerations or limitations

None

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant