Quantcast
Channel: PowerShell.org » All Posts
Viewing all articles
Browse latest Browse all 13067

Hashtable as resource parameter

$
0
0

I've been squeezing my brain trying to figure out how to get *-TargetResource to accept a [hashtable] parameter. Can it be done?

#psm1:
param([hashtable]$AdvancedProperties)
 
#schema:
[Write] String AdvancedProperties;

breaks with

Write-NodeMOFFile : Invalid MOF definition for node 'localhost': Exception calling "ValidateInstanceText" with "1"
argument(s): "Syntax error:
 At line:40, char:48
 Buffer:
 $MSFT_KeyValuePair1ref,^
   $M
"
At
C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:1457
char:17
+ …             Write-NodeMOFFile $name $mofNode $Script:NodeInstanceAlia …
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Write-Error], InvalidOperationException
    + FullyQualifiedErrorId : InvalidMOFDefinition,Write-NodeMOFFile

So that's no good, obviously.

#psm1:
param([hashtable]$AdvancedProperties)
 
#schema
[write] Hashtable AdvancedProperties;

is not recognized as a valid schema value at all, and the resource isn't registered with DSC.

#psm1:
param([hashtable]$AdvancedProperties)
 
#schema
[write, EmbeddedInstance("MSFT_KeyValuePair")] String AdvancedProperties;

breaks with the following error:

Write-NodeMOFFile : Invalid MOF definition for node 'localhost': Exception calling "ValidateInstanceText" with "1"
argument(s): "Syntax error:
 At line:40, char:48
 Buffer:
 $MSFT_KeyValuePair1ref,^
   $M
"
At
C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:1457
char:17
+ …             Write-NodeMOFFile $name $mofNode $Script:NodeInstanceAlia …
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Write-Error], InvalidOperationException
    + FullyQualifiedErrorId : InvalidMOFDefinition,Write-NodeMOFFile

And finally, I found a PowerShell Team person (http://blogs.msdn.com/b/powershell/archive/2013/11/19/resource-designer-tool-a-walkthrough-writing-a-dsc-resource.aspx) suggesting that it should be set up as such:

#psm1
param([Microsoft.Management.Infrastructure.CimInstance]$AdvancedProperties)
 
#schema
[write, EmbeddedInstance("MSFT_KeyValuePair")] String AdvancedProperties;

but that also fails with the same error as previously

Write-NodeMOFFile : Invalid MOF definition for node 'localhost': Exception calling "ValidateInstanceText" with "1"
argument(s): "Syntax error:
 At line:25, char:48
 Buffer:
 $MSFT_KeyValuePair1ref,^
   $M
"
At
C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:1457
char:17
+ …             Write-NodeMOFFile $name $mofNode $Script:NodeInstanceAlia …
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Write-Error], InvalidOperationException
    + FullyQualifiedErrorId : InvalidMOFDefinition,Write-NodeMOFFile

It breaks using both WMF4 and WMF5 Preview.

This is the configuration file I'm using:

configuration DSCModuleTest {
    param(
        [Parameter(Mandatory = $true)]
        [string]$ComputerName
    )
 
    Import-DscResource -ModuleName devNetAdapterModule
 
    Node $ComputerName {
        sNetAdapterAdvancedProperty Property {
            InterfaceAlias = 'Ethernet'
            AdvancedProperties = @{
                'Jumbo Packet'         = '1514'
                'Receive Side Scaling' = '1'
            }
        }
    }
}
 
DSCModuleTest -ComputerName 'localhost'

and the associated DSCResource as it looks currently:

######################################################################################
# The Get-TargetResource cmdlet.
# This function will get the working interface and its bindings
######################################################################################
function Get-TargetResource
{
    [CmdletBinding()]
	param
	(		
		[Parameter(Mandatory)]
		[ValidateNotNullOrEmpty()]
        [string]$InterfaceAlias
	)
 
    $properties = GetNetAdapterAdvancedProperty -InterfaceAlias $InterfaceAlias -Formatted
 
    Write-Output $properties
}
 
######################################################################################
# The Set-TargetResource cmdlet.
# This function will set the bindings of the selected interface
######################################################################################
function Set-TargetResource
{
    [CmdletBinding()]
	param
	(
		[Parameter(Mandatory)]
		[ValidateNotNullOrEmpty()]
        [string]$InterfaceAlias,
 
        [Parameter(Mandatory)]
        [hashtable]$AdvancedProperties
        #[Microsoft.Management.Infrastructure.CimInstance]$AdvancedProperties
	)
 
    $properties = GetNetAdapterAdvancedProperty -InterfaceAlias $InterfaceAlias
 
    foreach($key in $AdvancedProperties.Keys) {
        Write-Verbose ('Processing property {0}' -f $key)
 
        $property = $properties | Where-Object DisplayName -eq $key
        if($property -eq $null) {
            throw "Property $key not found. Use the Get-NetAdapterAdvancedProperty cmdlet to see available properties for your interface, and configure DSC AdvancedProperties hashtable to use 'DisplayName' property as key, and 'RegistryValue' as value."
        }
 
        Write-Verbose ('Found and now setting property {0}' -f $property.DisplayName)
        $property | Set-NetAdapterAdvancedProperty -RegistryValue $AdvancedProperties.$key
    }
}
 
######################################################################################
# The Test-TargetResource cmdlet.
# This will test if the interface bindings are as expected
######################################################################################
function Test-TargetResource
{
    [CmdletBinding()]
    param
	(		
		[Parameter(Mandatory)]
		[ValidateNotNullOrEmpty()]
		[string]$InterfaceAlias,
 
        [Parameter(Mandatory)]
        [hashtable]$AdvancedProperties
        #[Microsoft.Management.Infrastructure.CimInstance]$AdvancedProperties
	)
 
    $properties = GetNetAdapterAdvancedProperty -InterfaceAlias $InterfaceAlias -Formatted
 
    foreach($key in $AdvancedProperties.Keys) {
        Write-Verbose ('Processing property {0}' -f $key)
 
        $property = $properties | Where-Object DisplayName -eq $key
        if($property -eq $null) {
            throw "Property $key not found. Use the Get-NetAdapterAdvancedProperty cmdlet to see available properties for your interface, and configure DSC AdvancedProperties hashtable to use 'DisplayName' property as key, and 'RegistryValue' as value."
        }
 
        Write-Verbose ('Found and now testing property {0}' -f $property.DisplayName)
        if($property.RegistryValue -ne $AdvancedProperties.$key) {
            Write-Verbose ('Property "{0}" with expected value "{1}" does not match set value "{2}"' -f $key, $AdvancedProperties.$key, $property.RegistryValue)
            return $false
        }
    }
 
    return $true
}
 
 
#######################################################################################
#  Helper function that validates the IP Address properties. If the switch parameter
# "Apply" is set, then it will set the properties after a test
#######################################################################################
function GetNetAdapterByAlias {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$InterfaceAlias
    )
 
    Write-Verbose "Attempting to find NetAdapter using Alias $InterfaceAlias"
    $adapter = Get-NetAdapter -InterfaceAlias $InterfaceAlias
 
    if($adapter -ne $null -and @($adapter).Count -eq 1) {
        Write-Verbose ('Found {0}' -f $adapter.Name)
        return $adapter
    }
    else {
        if(@($adapter).Count -gt 1) { 
            throw ("Too many adapters found for Alias $InterfaceAlias ({0})" -f ($adapter.Name -join ', '))
        }
        elseif($adapter -eq $null) { 
            throw "No adapter found for Alias $InterfaceAlias"
        }
        else {
            throw ('Unexpected error? Adapter count: {0}. InterfaceAlias: {1}.' -f @($adapter).Count, $InterfaceAlias)
        }
    }
}
 
function GetNetAdapterAdvancedProperty {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$InterfaceAlias,
 
        [switch]$Formatted
    )
 
    $adapter = GetNetAdapterByAlias -InterfaceAlias $InterfaceAlias
 
    Write-Verbose "Getting advanced properties"
    $properties = $adapter | Get-NetAdapterAdvancedProperty
    if($properties -eq $null) {
        throw ("Unable to acquire bindings for NetAdapter {0}" -f $adapter.Name)
    }
 
    if($Formatted) { 
        Write-Verbose "Formatting properties"
        $returnValue = foreach($property in $properties) {
            Write-Output @{
                $property.DisplayName = $property.DisplayValue
            }
        }
 
	    Write-Output $returnValue
    }
    else {
        Write-Output $properties
    }
}
 
 
#  FUNCTIONS TO BE EXPORTED 
Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource

Viewing all articles
Browse latest Browse all 13067

Latest Images

Trending Articles



Latest Images