WebSites: Binding infos not supported
Problem description
Specifying the binding infos for a website, the MOF compilation fails.
Verbose logs
Write-NodeMOFFile : Invalid MOF definition for node 'localhost_WebSites': Exception calling "ValidateInstanceText" with "1" argument(s): "Convert property 'BindingInfo' value from type
'STRING[]' to type 'INSTANCE[]' failed
DSC configuration
Items:
- Name: TestSite1
ApplicationPool: TestAppPool1
BindingInfo:
Protocol: HTTPS
Port: 443
HostName: test.com
CertificateThumbprint: 466CD26A6E2F346A3A813D12E2BAAD0E886E7BBF
- Name: TestSite2
ApplicationPool: TestAppPool2
# Remove IIS Default WebSite
- Name: Default Web Site
Ensure: Absent
Operating system the target node is running
OsName : Microsoft Windows 10 Enterprise
OsOperatingSystemSKU : EnterpriseEdition
OsArchitecture : 64-bit
WindowsVersion : 2009
WindowsBuildLabEx : 19041.1.amd64fre.vb_release.191206-1406
OsLanguage : en-US
OsMuiLanguages : {en-US}
PowerShell version and build the target node is running
Name Value
---- -----
PSVersion 5.1.19041.1320
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.19041.1320
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
CommonTasks version
0.4
Assuming you're using the Website composite resource, and given its simple code here: https://github.com/dsccommunity/CommonTasks/blob/main/source/DSCResources/WebSites/Websites.schema.psm1#L23
I think the problem comes with Get-DscSplattedResource because it does not support MOF subtypes: https://github.com/dsccommunity/xWebAdministration/blob/main/source/DSCResources/MSFT_xWebSite/MSFT_xWebSite.schema.mof#L30
I think this problem does not happen with Class-based resources when the constructor of the nested type supports hashtable as parameter (which is and should be the default).
I appreciate that does not help solving the issue, but helps pin-pointing it.
Thank you Gael!
I got to manage it working in this way:
function Global:Get-DscSplattedResource {
[CmdletBinding()]
Param(
[String]
$ResourceName,
[String]
$ExecutionName,
[hashtable]
$Properties,
[switch]
$NoInvoke
)
# Remove Case Sensitivity of ordered Dictionary or Hashtables
$Properties = @{}+$Properties
$stringBuilder = [System.Text.StringBuilder]::new()
$null = $stringBuilder.AppendLine("Param([hashtable]`$Parameters)")
$null = $stringBuilder.AppendLine()
if($ExecutionName) {
$null = $stringBuilder.AppendLine(" $ResourceName '$ExecutionName' {")
}
else {
$null = $stringBuilder.AppendLine(" $ResourceName {")
}
foreach($PropertyName in $Properties.keys) {
$null = $stringBuilder.AppendLine("$PropertyName = `$(`$Parameters['$PropertyName'])")
}
$null = $stringBuilder.AppendLine("}")
Write-Debug ("Generated Resource Block = {0}" -f $stringBuilder.ToString())
if($NoInvoke) {
[scriptblock]::Create($stringBuilder.ToString())
}
else {
[scriptblock]::Create($stringBuilder.ToString()).Invoke($Properties)
}
}
Set-Alias -Name x -Value Get-DscSplattedResource -scope Global
configuration WebSites {
param (
[Parameter(Mandatory = $true)]
[hashtable[]]
$Items
)
Import-DscResource -ModuleName PSDesiredStateConfiguration
Import-DscResource -ModuleName xWebAdministration
foreach ($item in $Items)
{
# Remove Case Sensitivity of ordered Dictionary or Hashtables
$item = @{} + $item
if (-not $item.ContainsKey('Ensure'))
{
$item.Ensure = 'Present'
}
if ($item.ContainsKey('BindingInfo'))
{
$bindingInfo = $item.BindingInfo
$item.BindingInfo = (Get-DscSplattedResource -ResourceName MSFT_xWebBindingInformation -Properties $bindingInfo -NoInvoke).Invoke($bindingInfo)
}
$executionName = "website_$($item.Name -replace '[{}#\-\s]','_')"
(Get-DscSplattedResource -ResourceName xWebSite -ExecutionName $executionName -Properties $item -NoInvoke).Invoke($item)
}
}
Would you accept such modifications as PR for Get-DscSplattedResource in DscBuildHelpers module? Or is there something you think that needs to be better look at?
if($ExecutionName) {
$null = $stringBuilder.AppendLine(" $ResourceName '$ExecutionName' {")
}
else {
$null = $stringBuilder.AppendLine(" $ResourceName {")
}