Chris
Chris

Reputation: 444

Passing subset of objects down pipeline, based on count of properties?

I need to script up some things in PowerCLI (VMWare's bolt on to PowerShell). Basically we have a server cluster with three hosts. Each host has multiple virtual switches. Each virtual switch has multiple vlans ('port groups' in VMWare speak). I need to audit the fact that the same port groups exist on each host (so things keep working if the VM is moved).

Step 1 to achieving this is would be to know that the port group name exists on each of the three host machines.

I'm falling over with how to filter some objects out of all the ones returned by a cmdlet, based on number of results returned from a property of those objects. I then need to perform further operations with original object type that passes the filter test to go on down the pipeline.

To give some specifics, this an example showing 'Some PortGroup Name' and the three hosts it exists on (and as a bonus, the vSwitch):

Get-VirtualPortGroup -Name 'Some PortGroup Name' |
    Select-Object Name, VMHostID, VirtualSwitchId

produces the output

Name                VMHostId              VirtualSwitchId
----                --------              ---------------
Some PortGroup Name HostSystem-host-29459 key-vim.host.VirtualSwitch-vSwitch6
Some PortGroup Name HostSystem-host-29463 key-vim.host.VirtualSwitch-vSwitch6
Some PortGroup Name HostSystem-host-29471 key-vim.host.VirtualSwitch-vSwitch6

Instead of 3, I'm starting with the 1849 port group names that are being returned by Get-VirtualPortGroup. I need a pipeline to whittle the number of VirtualPortGroup objects down to a collection consisting of only those objects where a count of the 'VMHostId' property is less than 3, and pass the remaining VirtualPortGroup objects down the pipeline for further processing.

This seems simple enough to do. I'm still failing though.

The following almost works. Piping it to measure shows a count of 229, instead of the original 1849 (so it's definitely filtered a lot out, and is possibly correctly returning the subset I'm after...?). The problem is, the object type is now a 'Group' or something at this point in the pipeline, and doesn't have all the properties and methods of the original Get-VirtualPortGroup objects.

Get-VirtualPortGroup |
    Group-Object -Property Name |
    Where-Object $_.Count -lt 3

Bolting a | Select-Object -ExpandProperty Group to the end of the above seemed promising, except it then seems to return the entire collection of Get-VirtualPortGroup objects as though I had done no filtering in there at all....

Am I doing something fundamentally wrong?

How can I filter out objects based on the count of the number of results returned by a specific property of an object, but still pass the original object type down the pipe?

Upvotes: 3

Views: 285

Answers (1)

Ansgar Wiechers
Ansgar Wiechers

Reputation: 200443

Your approach is correct, but you got the Where-Object syntax wrong. The abbreviated syntax is:

Where-Object <property> <op> <value>

without the current object variable ($_). In your case that would be:

Where-Object Count -lt 3

Otherwise you must use scriptblock notation:

Where-Object { $_.Count -lt 3 }

This should do what you want:

Get-VirtualPortGroup |
    Group-Object -Property Name |
    Where-Object { $_.Count -lt 3 } |
    Select-Object -Expand Group

Upvotes: 3

Related Questions