Comparing Object Comparison with Hash List

I am looking for troubleshooting help comparing .key values ​​to objects.

Basically what happens here is I connect to two VMware vCenters and load a list of roles and put those roles into two hash tables and then compare them.

The problem comes down to the Process-Roles function, where the comparison logic is incorrect. It lists all roles in both lists. I think (-necontainer) is not working correctly. I have been debugging powerGUI and both hashtables and mstr_roles / slave_roles are filled in correctly.

Role lists must be object lists as they are populated with Get-VIRole. The hash table must be object-key, null-valued lists. Can the two be compared? I am trying to check if a $ role object exists in a list of roles in a .key hash table.

$creds = Get-Credential
$mst = Read-Host "`n Master Server: "
$slv = Read-Host "`n Slave Server: "
$hsh_mstr_roles = @{}
$hsh_slave_roles = @{}
$mstr_roles = ""
$slave_roles = ""

Get-Roles -MasterServer $mst -SlaveServer $slv

Process-Roles 

      

...

function Get-Roles() {
Param(
 [Parameter(Mandatory=$True,Position=0)]
 [string]$MasterServer,

 [Parameter(Mandatory=$True,Position=1)]
 [string]$SlaveServer
 )

#Get Master Roles
Connect-VIServer $MasterServer -Credential $creds

$mstr_roles = Get-VIrole

foreach ($role in $mstr_roles) {
    $hsh_mstr_roles.add($role, $null)
}

Disconnect-VIServer $MasterServer -Confirm:$false

#Get Slave Roles
Connect-VIServer $SlaveServer -Credential $creds

$slave_roles = Get-VIrole

foreach ($role in $slave_roles) {
    $hsh_slave_roles.add($role, $null)
}

Disconnect-VIServer $SlaveServer -Confirm:$false

Write-Host "`n + Retrieved Roles Successfully"
}    

      

...

function Process-Roles () { 
#Get Roles on Master NOT ON SLAVE

Write-Host "`n"

foreach ($role in $mstr_roles){
    if(-not $hsh_slave_roles.containsKey($role)){
    Write-Host $role "doesn't exist on slave"
    }
}

#Get Roles on Slave NOT ON MASTER
foreach ($role in $slave_roles){
    if(-not $hsh_mstr_roles.containsKey($role)){
    Write-Host $role "doesn't exist on master"
    }
}

Write-Host "`n + Processed Roles Successfully"
}

      

+3


source to share


2 answers


The easiest way to do this is to find the complement to one of the two sets of keys that each hash table has, using -notcontains

:

function Process-Roles {
    param(
        [hashtable]$MasterRoles,
        [hashtable]$SlaveRoles
    )

    # Complement to slave roles (those ONLY in $MasterRoles)
    $MasterRoles.Keys |Where-Object { $SlaveRoles -notcontains $_ }|ForEach-Object {
        Write-Host "$_ not in Slave Roles"
    } 

    # and the other way around (those ONLY in $SlaveRoles)
    $SlaveRoles.Keys |Where-Object { $MasterRoles -notcontains $_ }|ForEach-Object {
        Write-Host "$_ not in Master Roles"
    } 

}

      


I must add that your way of working with variables in different scopes is not optimal.

  • Determine the parameters required for the function to do its job
  • Returns output from your functions where it makes sense (any function Get-*

    should be a minimum)
  • Depends on global and Script scopes as little as possible, preferably not all

Instead, I would do something like this:

Add a parameter Credential

to the function Get-Roles

and return the results, rather than modifying the variable in the parent scope (here using the Role Category Hashtable):



function Get-Roles {
    Param(
        [Parameter(Mandatory=$True,Position=0)]
        [string]$MasterServer,

        [Parameter(Mandatory=$True,Position=1)]
        [string]$SlaveServer,

        [Parameter(Mandatory=$True,Position=2)]
        [pscredential]$Credential
    )

    $DiscoveredRoles = @{}

    # Get Master Roles
    Connect-VIServer $MasterServer -Credential $Credential
    $DiscoveredRoles["MasterRoles"] = Get-VIRole
    Disconnect-VIServer $MasterServer -Confirm:$false

    #Get Slave Roles
    Connect-VIServer $SlaveServer -Credential $Credential
    $DiscoveredRoles["SlaveRoles"] = Get-VIrole
    Disconnect-VIServer $SlaveServer -Confirm:$false

    Write-Verbose "`n + Retrieved Roles Successfully"

    return $DiscoveredRoles

}    

      

Define the parameters for the function Process-Roles

that match the hash table you expect to generate from, Get-Roles

and do the same comparison of role names as above, only this time we grab them directly from the Role objects:

function Process-Roles { 
    param(
        [Parameter(Mandatory=$true)]
        [ValidateScript({ $_.ContainsKey("MasterRoles") -and $_.ContainsKey("SlaveRoles") })]
        [hashtable]$RoleTable
    )

    $MasterRoleNames = $RoleTable["MasterRoles"] |Select-Object -ExpandProperty Name

    $SlaveRoleNames = $RoleTable["SlaveRoles"] |Select-Object -ExpandProperty Name

    $MasterRoleNames |Where-Object { $SlaveRoleNames -notcontains $_ } |ForEach-Object {
        Write-Host "$_ doesn't exist on slave"    
    }

    $SlaveRoleNames |Where-Object { $MasterRoleNames -notcontains $_ } |ForEach-Object {
        Write-Host "$_ doesn't exist on Master"    
    }

    Write-Host "`n + Processed Roles Successfully"
}

      

Update your Script executable with new parameters:

$creds = Get-Credential
$MasterServer = Read-Host "`n Master Server: "
$SlaveServer  = Read-Host "`n Slave Server: "

$RoleTable = Get-Roles -MasterServer $MasterServer -SlaveServer $SlaveServer -Credential $creds

Process-Roles -RoleTable $RoleTable

      

The next step would be to add pipeline support to the function Process-Roles

, convert operators Write-Host

to, Write-Verbose

and add error handling, but I'll leave that as an exercise for the OP :-)

+3


source


try:



if(!$hsh_slave_roles.containsKey($role))

      

+1


source







All Articles