Private/Select-ArmorApiResult.ps1
function Select-ArmorApiResult { <# .SYNOPSIS Criteria-based object filtering. .DESCRIPTION Filters objects returned from an Armor API endpoint for result object property values matching parameter values. Wildcard filtering is supported via the use of the `-like` operator. .INPUTS System.Management.Automation.PSObject[] .INPUTS System.Management.Automation.PSObject .NOTES - Troy Lindsay - Twitter: @troylindsay42 - GitHub: tlindsay42 .EXAMPLE $results = Invoke-ArmorRestMethod -Uri 'https://api.armor.com/vms'; $filters = $resources.Filter | Get-Member -MemberType 'NoteProperty'; $results = Select-ArmorApiResult -Results $results -Filters $filters Sets $results to the VMs matching the parameters defined in the calling cmdlet: `Get-ArmorVM`, such as 'Name'='TEST-VM'. There are no available use cases for the bi-level filter yet, but one example is to define a filter key in ApiData.json such as `"SKU": "Product.SKU"`, and then define a $SKU parameter for `Get-ArmorVM`, so that you could then filter for VMs by SKU via the `Get-ArmorVM` cmdlet. .LINK https://tlindsay42.github.io/ArmorPowerShell/private/Select-ArmorApiResult/ .LINK https://github.com/tlindsay42/ArmorPowerShell/blob/master/Armor/Private/Select-ArmorApiResult.ps1 .LINK https://docs.armor.com/display/KBSS/Armor+API+Guide .LINK https://developer.armor.com/ .COMPONENT Armor API .FUNCTIONALITY Armor API client-side response filtering #> [CmdletBinding()] [OutputType( [PSCustomObject[]] )] [OutputType( [PSCustomObject] )] param ( # Specifies the formatted API response contents. [Parameter( Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true )] [AllowEmptyCollection()] [PSCustomObject[]] $Results = @(), <# Specifies the list of parameters that the user can use to filter response data. Each key is the parameter name without the "$" and each value corresponds to the response data's key. If a '.' is included in the key name, the filter key name will be split so that the first part of the filter key will be applied to a root-level property in the result object, and the second part will be applied to a child property within the parent property. #> [Parameter( Position = 1 )] [AllowEmptyCollection()] [PSCustomObject[]] $Filters = @() ) begin { $function = $MyInvocation.MyCommand.Name Write-Verbose -Message "Beginning: '${function}' with ParameterSetName '$( $PSCmdlet.ParameterSetName )' and Parameters: $( $PSBoundParameters | Out-String )" } process { [PSCustomObject[]] $return = $null if ( ( $Results | Measure-Object ).Count -eq 0 -or ( $Filters | Measure-Object ).Count -eq 0 ) { $return = $Results } else { $filteredResults = $Results.Clone() $filteredResultsCount = ( $filteredResults | Measure-Object ).Count Write-Verbose -Message 'Filter the results.' foreach ( $filter in $Filters ) { $filterValueName = $filter.Definition.Split( '=' )[-1] $filterValue = ( Get-Variable -Name $filter.Name -ErrorAction 'SilentlyContinue' ).Value.ToString() if ( $filterValue.Length -gt 0 ) { Write-Verbose -Message "Filter match = ${filterValueName}=${filterValue}" if ( $filterValueName -match '\.' ) { $filterList = $filterValueName.Split( '.' ) } else { $filterList = @( $filterValueName ) } $filterListCount = ( $filterList | Measure-Object ).Count Write-Verbose -Message "Filter depth: '${filterListCount}'" switch ( $filterListCount ) { 1 { Write-Verbose -Message "Results count pre-filter: '${filteredResultsCount}'" $filteredResults = $filteredResults | Where-Object -FilterScript { $_ | Get-Member -Name $filterValueName -ErrorAction 'SilentlyContinue' } | Where-Object -FilterScript { $_.$filterValueName -like $filterValue } $filteredResultsCount = ( $filteredResults | Measure-Object ).Count Write-Verbose -Message "Results count post-filter: '${filteredResultsCount}'" } 2 { $parentFilter = $filterList[0] $childFilter = $filterList[1] if ( $parentFilter -eq '' -or $childFilter -eq '' ) { throw "Invalid Armor API filter configuration: '${filterValue}'" } Write-Verbose -Message "Results count pre-filter: '${filteredResultsCount}'" $filteredResults = $filteredResults | Where-Object -FilterScript { $_ | Get-Member -Name $parentFilter -ErrorAction 'SilentlyContinue' } | Where-Object -FilterScript { $_.$parentFilter | Get-Member -Name $childFilter -ErrorAction 'SilentlyContinue' } | Where-Object -FilterScript { $_.$parentFilter.$childFilter -like $filterValue } $filteredResultsCount = ( $filteredResults | Measure-Object ).Count Write-Verbose -Message "Results count post-filter: '${filteredResultsCount}'" } default { throw "Unsupported Armor API filter configuration: '${filterValue}'" } } } } $return = $filteredResults } $return } end { Write-Verbose -Message "Ending: '${function}'." } } |