Modules/M365DSCConfigurationCompiler.psm1
|
# Compiles exported tenant configurations through the M365DSCFastHost-capable # PSDesiredStateConfiguration engine when one is available (see # docs/FastHostContract.md in the engine repository). function Get-M365DSCDscEngineManifest { [CmdletBinding()] [OutputType([System.String])] param () $installed = Get-Module -ListAvailable -Name M365DSC.PSDesiredStateConfiguration | Where-Object { $_.PrivateData.PSData.Tags -contains 'M365DSCFastHost' } | Sort-Object -Property Version -Descending | Select-Object -First 1 if ($installed) { return $installed.Path } return $null } function Test-M365DSCFastCompileAvailable { [CmdletBinding()] [OutputType([System.Boolean])] param () $null -ne (Get-M365DSCDscEngineManifest) } function Import-M365DSCDscEngine { [CmdletBinding()] param () $manifest = Get-M365DSCDscEngineManifest if (-not $manifest) { throw 'No M365DSCFastHost-capable M365DSC.PSDesiredStateConfiguration engine was found.' } $manifestBase = Split-Path -Path $manifest -Parent $loaded = Get-Module -Name M365DSC.PSDesiredStateConfiguration | Where-Object -Property ModuleBase -EQ -Value $manifestBase if (-not $loaded) { Get-Module -Name M365DSC.PSDesiredStateConfiguration | Remove-Module -Force Import-Module -Name $manifest -Force -Global } } <# .SYNOPSIS Compiles an exported Microsoft365DSC configuration script to MOF. .DESCRIPTION Uses the fast compile host of the M365DSC.PSDesiredStateConfiguration engine when installed (seconds instead of minutes for class-based resources) and falls back to standard compilation otherwise. .PARAMETER Path Path to the exported configuration script. Defaults to .\M365TenantConfig.ps1. .PARAMETER ConfigurationDataPath Path to the configuration data .psd1. Defaults to ConfigurationData.psd1 next to the configuration script when present. .PARAMETER ConfigurationData Configuration data as an in-memory hashtable, for callers that do not have it on disk. Takes precedence over ConfigurationDataPath. .PARAMETER ConfigurationName Name of the configuration to compile. Required when the script only declares a configuration instead of invoking one. .PARAMETER Credential Credential forwarded to the configuration's -Credential parameter. .PARAMETER CertificatePassword CertificatePassword forwarded to the configuration's -CertificatePassword parameter. .PARAMETER Parameters Additional parameters splatted onto the configuration invocation. .PARAMETER Engine Auto (default) uses the fast host when available; FastHost requires it; Standard always compiles through the standard configuration pipeline. .PARAMETER OutputPath Folder for the generated MOF files. .EXAMPLE Invoke-M365DSCConfigurationBuild -Path .\M365TenantConfig.ps1 #> function Invoke-M365DSCConfigurationBuild { [CmdletBinding()] param ( [Parameter()] [System.String] $Path = '.\M365TenantConfig.ps1', [Parameter()] [System.String] $ConfigurationDataPath, [Parameter()] [System.Object] $ConfigurationData, [Parameter()] [System.String] $ConfigurationName, [Parameter()] [System.Management.Automation.PSCredential] $Credential, [Parameter()] [System.Management.Automation.PSCredential] $CertificatePassword, [Parameter()] [System.Collections.Hashtable] $Parameters, [Parameter()] [ValidateSet('Auto', 'FastHost', 'Standard')] [System.String] $Engine = 'Auto', [Parameter()] [System.String] $OutputPath ) $Path = (Resolve-Path -Path $Path).ProviderPath if (-not $ConfigurationDataPath -and $null -eq $ConfigurationData) { $candidate = Join-Path -Path (Split-Path -Path $Path -Parent) -ChildPath 'ConfigurationData.psd1' if (Test-Path -Path $candidate) { $ConfigurationDataPath = $candidate } } $invokeParameters = @{} if ($Parameters) { $invokeParameters = $Parameters.Clone() } if ($Credential) { $invokeParameters['Credential'] = $Credential } if ($CertificatePassword) { $invokeParameters['CertificatePassword'] = $CertificatePassword } $useFastHost = $false switch ($Engine) { 'FastHost' { Import-M365DSCDscEngine $useFastHost = $true } 'Auto' { if (Test-M365DSCFastCompileAvailable) { Import-M365DSCDscEngine $useFastHost = $true } else { Write-Warning -Message 'No fast-compile-capable DSC engine found; compiling through the standard pipeline.' } } 'Standard' { if (Test-M365DSCFastCompileAvailable) { Import-M365DSCDscEngine } } } if ($useFastHost) { $fastArguments = @{ Path = $Path } if ($ConfigurationName) { $fastArguments['ConfigurationName'] = $ConfigurationName } if ($null -ne $ConfigurationData) { $fastArguments['ConfigurationData'] = $ConfigurationData } elseif ($ConfigurationDataPath) { $fastArguments['ConfigurationData'] = $ConfigurationDataPath } if ($invokeParameters.Count -gt 0) { $fastArguments['Parameters'] = $invokeParameters } if ($OutputPath) { $fastArguments['OutputPath'] = $OutputPath } return Invoke-DscFastCompile @fastArguments } # Standard pipeline: run the script itself. The recursion guard makes its # trailer take the plain invocation branch. $Global:PSDscFastCompileActive = $true try { $scriptDirectory = Split-Path -Path $Path -Parent Push-Location -Path $scriptDirectory try { if (-not $ConfigurationName) { return (& $Path @invokeParameters) } # The script only declares the configuration, so dot-source and invoke it. . $Path try { if ($OutputPath) { $invokeParameters['OutputPath'] = $OutputPath } $data = if ($null -ne $ConfigurationData) { $ConfigurationData } elseif ($ConfigurationDataPath) { Import-PowerShellDataFile -Path $ConfigurationDataPath } else { $null } if ($null -ne $data) { $invokeParameters['ConfigurationData'] = $data } return (& $ConfigurationName @invokeParameters) } finally { Remove-Item -Path "function:$ConfigurationName" -Force -Recurse -ErrorAction 'SilentlyContinue' } } finally { Pop-Location } } finally { $Global:PSDscFastCompileActive = $false } } Export-ModuleMember -Function Invoke-M365DSCConfigurationBuild, Test-M365DSCFastCompileAvailable |