Skip to content

Commit

Permalink
Draft of the configuration and resource DSL
Browse files Browse the repository at this point in the history
  • Loading branch information
claudiospizzi committed Sep 11, 2021
1 parent 12c2a38 commit be2b02d
Show file tree
Hide file tree
Showing 5 changed files with 245 additions and 1 deletion.
39 changes: 39 additions & 0 deletions PSDscExecutor/Functions/DscExecConfiguration.ps1
@@ -0,0 +1,39 @@
<#
.SYNOPSIS
.
.DESCRIPTION
.
.INPUTS
.
.OUTPUTS
.
.EXAMPLE
PS C:\> DscExecConfiguration
.
.LINK
https://github.com/claudiospizzi/PSDscExecutor
#>
function DscExecConfiguration
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, Position = 0)]
[System.Management.Automation.ScriptBlock]
$Definition
)

try
{
& $Definition | Out-Null
}
catch
{
$PSCmdlet.ThrowTerminatingError($_)
}
}
148 changes: 148 additions & 0 deletions PSDscExecutor/Functions/DscExecResource.ps1
@@ -0,0 +1,148 @@
<#
.SYNOPSIS
.
.DESCRIPTION
.
.INPUTS
.
.OUTPUTS
.
.EXAMPLE
PS C:\> DscExecResource
.
.LINK
https://github.com/claudiospizzi/PSDscExecutor
#>
function DscExecResource
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, Position = 0)]
[System.String]
$ModuleName,

[Parameter(Mandatory = $true, Position = 1)]
[System.String]
$ResourceName,

[Parameter(Mandatory = $true, Position = 2)]
[System.String]
$Name,

[Parameter(Mandatory = $true, Position = 3)]
[System.Collections.Hashtable]
$Property
)

try
{
if ($ModuleName.Contains('@'))
{
# The module definition contains the required version. Extract the
# version of the definition and the get the DSC resource.
$ModuleName, $moduleVersion = $ModuleName.Split('@', 2)
$dscResource = Get-DscResource -Module @{ ModuleName = $ModuleName; RequiredVersion = $moduleVersion } -Name $ResourceName
}
else
{
# Get the DSC resource right away. Check if the DSC resource was
# loaded and extract the version.
$dscResource = Get-DscResource -Module $ModuleName -Name $ResourceName
$moduleVersion = $dscResource.Version
if ($null -eq $moduleVersion)
{
$moduleVersion = 'n/a'
if ($dscResource.Path -like 'C:\Windows\System32\WindowsPowershell\v1.0\Modules\PSDesiredStateConfiguration\DscResources\*')
{
$moduleVersion = '1.1'
}
}
}

# Verify all mandatory properties are part of the provided properties
# and extract them in a dedicated hash table.
$keyProperties = @{}
foreach ($propertyKey in $dscResource.Properties.Where({ $_.IsMandatory }).Name)
{
if ($Property.Keys -notcontains $propertyKey)
{
throw "The mandatory property $propertyKey is not specified in $ModuleName@$moduleVersion/$ResourceName/$Name."
}
$keyProperties[$propertyKey] = $Property[$propertyKey]
}

# Copy and verify all provided properties.
$allProperties = @{}
foreach ($propertyKey in $Property.Keys)
{
if ($dscResource.Properties.Name -notcontains $propertyKey)
{
throw "The property $propertyKey not found in the resource $ModuleName@$moduleVersion/$ResourceName."
}
$allProperties[$propertyKey] = $Property[$propertyKey]
}

# Prepare all the DSC invocation helpers
$invokeDscResourceVerbose = "[$ModuleName@$moduleVersion] [$ResourceName] [$Name]"
# $verboseResourceName = "[$ModuleName@$moduleVersion] [$ResourceName] [$Name]"
# $verboseResourceSpace = "[$ModuleName@$moduleVersion] [$ResourceName]" -replace '.', ' '
# $verboseInstanceName = "$verboseResourceName [$Name]"
# $verboseInstanceSpace = $verboseInstanceName -replace '.', ' '
$invokeDscResourceSplat = @{
Name = $ResourceName
ModuleName = @{
ModuleName = $ModuleName
RequiredVersion = $moduleVersion
}
}

Write-Verbose $invokeDscResourceVerbose

# Loop over the resource as long as it is not in the desired state.
$inDesiredState = $false
while (-not $inDesiredState)
{
Write-Verbose "$invokeDscResourceVerbose [Test] Start"

$inDesiredState = Invoke-DscResource @invokeDscResourceSplat -Method 'Test' -Property $allProperties | Select-Object -ExpandProperty 'InDesiredState'

Write-Verbose "$invokeDscResourceVerbose [Test] DesiredState = $inDesiredState"

Write-Verbose "$invokeDscResourceVerbose [Test] End"

if (-not $inDesiredState)
{
Write-Verbose "$invokeDscResourceVerbose [Set] Start"

Invoke-DscResource @invokeDscResourceSplat -Method 'Set' -Property $allProperties

Write-Verbose "$invokeDscResourceVerbose [Set] End"
}
}

Write-Verbose "$invokeDscResourceVerbose [Get] Start"

$stateData = Invoke-DscResource @invokeDscResourceSplat -Method 'Get' -Property $keyProperties

foreach ($stateDataPropertyKey in $stateData.Keys)
{
Write-Verbose "$invokeDscResourceVerbose [Get] $stateDataPropertyKey = $($stateData[$stateDataPropertyKey])"
}

Write-Verbose "$invokeDscResourceVerbose [Get] End"

Write-Verbose $invokeDscResourceVerbose

return $stateData
}
catch
{
$PSCmdlet.ThrowTerminatingError($_)
}
}
51 changes: 51 additions & 0 deletions PSDscExecutor/Helpers/Register-DscResourceFunction.ps1
@@ -0,0 +1,51 @@
<#
.SYNOPSIS
.
.DESCRIPTION
.
.INPUTS
.
.OUTPUTS
.
.EXAMPLE
PS C:\> Register-DscResourceFunction
.
.LINK
https://github.com/claudiospizzi/PSDscExecutor
#>
function Register-DscResourceFunction
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, ValueFromPipeline = $true)]
[Microsoft.PowerShell.DesiredStateConfiguration.DscResourceInfo]
$DscResourceInfo,

[Parameter(Mandatory = $false)]
[ValidateSet('Script', 'Global')]
[System.String]
$Scope = 'Script'
)

begin
{
try
{
# Resource with no module name?!?
$functionName = '{0}:{1}@{2}\{3}' -f $Scope, $DscResourceInfo.ModuleName, $DscResourceInfo.Version, $DscResourceInfo.Name
$functionCode = [System.Management.Automation.ScriptBlock]::Create('param ($A) Write-Host "A: $A"')

New-Item -Path 'Function:\' -Name $functionName -Value $functionCode | Out-Null
}
catch
{
$PSCmdlet.ThrowTerminatingError($_)
}
}
}
5 changes: 4 additions & 1 deletion PSDscExecutor/PSDscExecutor.psd1
Expand Up @@ -64,7 +64,10 @@
NestedModules = @()

# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export.
FunctionsToExport = @()
FunctionsToExport = @(
'DscExecConfiguration'
'DscExecResource'
)

# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
CmdletsToExport = @()
Expand Down
3 changes: 3 additions & 0 deletions PSDscExecutor/PSDscExecutor.psm1
Expand Up @@ -33,3 +33,6 @@ $Script:PSModuleVersion = (Import-PowerShellDataFile -Path "$Script:PSModulePath
# Define module behaviour
$ErrorActionPreference = 'Stop'
Set-StrictMode -Version 'Latest'

# Now, register all available DSC resource functions
# Get-DscResource | Register-DscResourceFunction -Scope 'Script'

0 comments on commit be2b02d

Please sign in to comment.