4

Forgive me, but I don't know the correct terminology for this.

Assuming the following hashtable:

$ConfigurationData = @{
    AllNodes = @(
        @{
            NodeName="*"
            PSDscAllowPlainTextPassword=$True
            PsDscAllowDomainUser=$True
        }
    )
}

How do I make it look like this:

$ConfigurationData = @{
    AllNodes = @(
        @{
            NodeName="*"
            PSDscAllowPlainTextPassword=$True
            PsDscAllowDomainUser=$True
            NewItem = "SomeNewValue"
            AnotherNewItem = "Hello"
        }
    )
}

I can do:

$ConfigurationData.AllNodes += @{NewItem = "SomeNewValue"}
$ConfigurationData.AllNodes += @{AnotherNewItem  = "Hello"}

And doing $ConfgurationData.AllNodes looks right:

$ConfigurationData.AllNodes

Name                           Value                                                                                                                                            
----                           -----                                                                                                                                            
NodeName                       *                                                                                                                                                
PSDscAllowPlainTextPassword    True                                                                                                                                             
PsDscAllowDomainUser           True                                                                                                                                             
NewItem                        SomeNewValue                                                                                                                                     
AnotherNewItem                 Hello  

But converting it to JSON tells a different story:

$ConfigurationData | ConvertTo-Json
{
    "AllNodes":  [
                     {
                         "NodeName":  "*",
                         "PSDscAllowPlainTextPassword":  true,
                         "PsDscAllowDomainUser":  true
                     },
                     {
                         "NewItem":  "SomeNewValue"
                     },
                     {
                         "AnotherNewItem":  "Hello"
                     }
                 ]
}

NewItem and AnotherNewItem are in their own hashtable and not in the first one and this causes DSC to throw a wobbly:

ValidateUpdate-ConfigurationData : all elements of AllNodes need to be hashtable and has a property NodeName.


I can do the following which gives me the right result:

$ConfigurationData = @{
    AllNodes = @(
        @{
            NodeName="*"
            PSDscAllowPlainTextPassword=$True
            PsDscAllowDomainUser=$True
        }
    )
}

#$ConfigurationData.AllNodes += @{NewItem = "SomeNewValue"}
#$ConfigurationData.AllNodes += @{AnotherNewItem  = "Hello"}

foreach($Node in $ConfigurationData.AllNodes.GetEnumerator() | Where-Object{$_.NodeName -eq "*"}) 
{
            $node.add("NewItem", "SomeNewValue")
            $node.add("AnotherNewItem", "Hello")
}

$ConfigurationData | ConvertTo-Json
{
    "AllNodes":  [
                     {
                         "NodeName":  "*",
                         "PSDscAllowPlainTextPassword":  true,
                         "NewItem":  "SomeNewValue",
                         "AnotherNewItem":  "Hello",
                         "PsDscAllowDomainUser":  true
                     }
                 ]
}

But this seems overkill, compared to a line like $ConfigurationData.AllNodes += @{NewItem = "SomeNewValue"}

I've also tried and failed with:

$ConfigurationData.AllNodes.GetEnumerator() += @{"NewItem" = "SomeNewValue"}

Is there a similar way to target the right "element"?

3 Answers 3

3

This line is adding an item at the array level.

$ConfigurationData.AllNodes += @{NewItem = "SomeNewValue"}

In actuality, you want to add to the first element of the array, which is your hashtable:

($ConfigurationData.AllNodes)[0] += @{"new item" = "test"}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. So simple. Why didn't I think of that. Dsc compilation is happy too.
3

Your issue occurs because of the @() brackets you've put in your initial declaration of $ConfigurationData around the internal hashtable, which make it an array.

Per the answer from gms0ulman you need to use the array index operator to access an index of this array and then modify the properties there. E.g for the first element:

$ConfigurationData.AllNodes[0].'NewItem' = 'SomeNewValue'
$ConfigurationData.AllNodes[0].'AnotherNewItem' = 'Hello'

2 Comments

Thank you. Although the JSON output is correct, removing @(), the DSC fails to compile. Same error I cited in the Qu. (I know I didn't ask about DSC explicitly, but others may find this page hitting the same DSC problem).
Modified my answer, but basically gms0ulman is correct. @() is declaring allnodes as an array, which you are then populating with a hashtable, so you need to access its array index.
0

Actually, the only thing I didn't try:

$ConfigurationData = @{
    AllNodes = @(
        @{
            NodeName="*"
            PSDscAllowPlainTextPassword=$True
            PsDscAllowDomainUser=$True
        }
    )
}

$ConfigurationData.AllNodes.GetEnumerator().Add("NewItem","SomeNewValue")

$ConfigurationData.AllNodes.GetEnumerator().Add("AnotherNewItem","Hello")

$ConfigurationData | ConvertTo-Json




{
    "AllNodes":  [
                     {
                         "NodeName":  "*",
                         "PSDscAllowPlainTextPassword":  true,
                         "NewItem":  "SomeNewValue",
                         "AnotherNewItem":  "Hello",
                         "PsDscAllowDomainUser":  true
                     }
                 ]
}

I kind of understand the GetEnumerator bit. It creates an index - of sorts, so PS can work with the items.

But I don't get why I have to use the .Add() method and the +=@{} didn't work.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.