Functions/Public/Endpoints.ps1

# Endpoint management and testing functions

Function Get-NectarEndpoint {
    <#
        .SYNOPSIS
        Returns a list of Nectar DXP endpoints
 
        .DESCRIPTION
        Returns a list of Nectar DXP endpoints
 
        .PARAMETER SearchQuery
        A string to search for. Will search for match against all fields
         
        .PARAMETER OrderByField
        Sort the output by the selected field
         
        .PARAMETER OrderDirection
        Sort ordered output in ascending or descending order
         
        .PARAMETER TenantName
        The name of the Nectar DXP tenant. Used in multi-tenant configurations.
         
        .PARAMETER PageSize
        The size of the page used to return data. Defaults to 1000
         
        .PARAMETER ResultSize
        The total number of results to return. Defaults to 100000. Maximum result size is 9,999,999 results
         
        .EXAMPLE
        Get-NectarEndpoint
        Returns the first 100000 endpoints
         
        .EXAMPLE
        Get-NectarEndpoint -ResultSize 100
        Returns the first 100 endpoints
 
        .EXAMPLE
        Get-NectarEndpoint -SearchQuery US
        Returns all endpoints that have US in any of the data fields
 
        .NOTES
        Version 1.0
    #>

    
    [Alias("gne")]    
    Param (
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$SearchQuery,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [ValidateSet('id','uuid','name','ipAddress','isHub','mapped','userName','userDisplayName','location', IgnoreCase=$False)]
        [string]$OrderByField = 'id',
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [ValidateSet('asc','desc', IgnoreCase=$False)]
        [string]$OrderDirection = 'asc',
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$TenantName,
        [Parameter(Mandatory=$False)]
        [ValidateRange(1,100000)]
        [int]$PageSize = 1000,
        [Parameter(Mandatory=$False)]
        [ValidateRange(1,100000)]
        [int]$ResultSize = 100000
    )
    
    Begin {
        Connect-NectarCloud
    }        
    Process {
        Try {
            # Use globally set tenant name, if one was set and not explicitly included in the command
            If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { 
                $TenantName = $Global:NectarTenantName 
            } ElseIf ($TenantName) {
                If ($TenantName -NotIn $Global:NectarTenantList) {
                    $TList = $Global:NectarTenantList -join ', '
                    Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)"
                }
            }
            
            $URI = "https://$Global:NectarCloud/aapi/testing/entities"
            
            $Params = @{
                'orderByField' = $OrderByField
                'orderDirection' = $OrderDirection
            }
            
            If ($SearchQuery) { $Params.Add('searchQuery', $SearchQuery) }
            
            If ($ResultSize) { 
                $Params.Add('pageSize', $ResultSize) 
            }
            Else { 
                $Params.Add('pageSize', $PageSize)
            }

            If ($TenantName) { $Params.Add('tenant', $TenantName) }            
            

            $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader -Body $Params
            If ($TenantName) { $JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty } # Add the tenant name to the output which helps pipelining
            $JSON.elements
            
            $TotalPages = $JSON.totalPages
        
            If ($TotalPages -gt 1 -and !($ResultSize)) {
                $PageNum = 2
                Write-Verbose "Page size: $PageSize"
                While ($PageNum -le $TotalPages) {
                    Write-Verbose "Working on page $PageNum of $TotalPages"
                    $PagedURI = $URI + "?pageNumber=$PageNum"
                    $JSON = Invoke-RestMethod -Method GET -URI $PagedURI -Headers $Global:NectarAuthHeader -Body $Params
                    If ($TenantName) { $JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty }
                    $JSON.elements
                    $PageNum++
                }
            }
        }
        Catch {
            Write-Error "Unable to retrieve endpoint information. $($_.Exception.Message)"
            If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ }        
        }
    }
}


Function Set-NectarEndpoint {
    <#
        .SYNOPSIS
        Modify properties of a Nectar DXP endpoint
 
        .DESCRIPTION
        Modify properties of a Nectar DXP endpoint
 
        .PARAMETER SearchQuery
        A string to search for to return a specific endpoint. Will search for match against all fields
         
        .PARAMETER UserName
        The username to associate with the given endpoint. Set to $NULL to de-associate a user with an endpoint
         
        .PARAMETER IsHub
        Set the endpoint to be a hub endpoint or not.
         
        .PARAMETER TenantName
        The name of the Nectar DXP tenant. Used in multi-tenant configurations.
         
        .EXAMPLE
        Set-NectarEndpoint -SearchQuery ff4bf84a-04d8-11ec-ad2e-17d4f8d1df89 -UserName tferguson@contoso.com -IsHub $False
        Sets a specific endpoint's associated username to 'tferguson'
         
        .NOTES
        Version 1.0
    #>

    
    [Alias("gne")]    
    Param (
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)]
        [Alias('UUID')]
        [string]$SearchQuery,
        [Parameter(Mandatory=$False)]
        [string]$UserName,
        [Parameter(Mandatory=$False)]
        [string]$DisplayName,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [bool]$IsHub,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$TenantName,
        [Parameter(Mandatory=$False)]
        [ValidateRange(1,100000)]
        [int]$PageSize = 1000,
        [Parameter(Mandatory=$False)]
        [ValidateRange(1,100000)]
        [int]$ResultSize = 100000
    )
    
    Begin {
        Connect-NectarCloud

        # Use globally set tenant name, if one was set and not explicitly included in the command
        If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { 
                $TenantName = $Global:NectarTenantName 
            } ElseIf ($TenantName) {
                If ($TenantName -NotIn $Global:NectarTenantList) {
                    $TList = $Global:NectarTenantList -join ', '
                    Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)"
                }
            }
        
        $ECSearchURI = "https://$Global:NectarCloud/aapi/testing/entities/"
        $ECUpdateURI = "https://$Global:NectarCloud/aapi/testing/entity/"
        $UserNameURI = "https://$Global:NectarCloud/aapi/testing/entities/usernames/"
    }        
    Process {
        Try {    

            # Search for a single valid endpoint. Throw error if zero or more than 1 endpoint returned
            $ECSearchParams = @{
                'searchQuery' = $SearchQuery
            }
            
            If ($TenantName) { $ECSearchParams.Add('tenant', $TenantName) }

            $ECSearchJSON = Invoke-RestMethod -Method GET -URI $ECSearchURI -Headers $Global:NectarAuthHeader -Body $ECSearchParams
            
            If ($ECSearchJSON.totalElements -gt 1) {
                Write-Error 'Too many endpoints returned. Please refine your search query to return only a single endpoint.'
                Return
            }
            ElseIf ($ECSearchJSON.totalElements -eq 0) {
                Write-Error "Could not find endpoint $SearchQuery"
                Return
            }
            
            $EndpointDetails = $ECSearchJSON.elements
            
            # Search for a single valid username. Throw error if zero or more than 1 username returned
            If ($UserName) {
                $UserNameParams = @{
                    'searchQuery' = $UserName
                }
                
                If ($TenantName) { $UserNameParams.Add('tenant', $TenantName) }

                $UserSearchJSON = Invoke-RestMethod -Method GET -URI $UserNameURI -Headers $Global:NectarAuthHeader -Body $UserNameParams
                
                If ($UserSearchJSON.Count -gt 1) {
                    Write-Error 'Too many usernames returned. Please refine your search query to return only a single username.'
                    Return
                }
                ElseIf ($UserSearchJSON.Count -eq 0) {
                    Write-Error "Could not find user with name $UserName"
                    Return
                }
                
                $UserName = $UserSearchJSON.UserName
            }
            
            If ($PSBoundParameters.Keys.Contains('UserName')) {
                If ($UserName) {
                    $EndpointDetails[0].userName = $UserName
                }
                Else {
                    $EndpointDetails[0].userName = $NULL
                }
            }
            
            If ($DisplayName) { $EndpointDetails[0].userDisplayName = $DisplayName }

            If ($PSBoundParameters.Keys.Contains('IsHub')) { 
                $EndpointDetails[0].IsHub = $IsHub 
                $EndpointDetails[0].userName = $NULL
            }
            
            $EndpointJSON = $EndpointDetails | ConvertTo-Json
            
            Write-Verbose $EndpointJSON
            
            If ($TenantName) { $ECUpdateURI = $ECUpdateURI + "?tenant=$TenantName" }
            
            $NULL = Invoke-RestMethod -Method PUT -URI $ECUpdateURI -Headers $Global:NectarAuthHeader -Body $EndpointJSON -ContentType 'application/json; charset=utf-8'
        }
        Catch {
            Write-Error "Unable to set endpoint information. $($_.Exception.Message)"
            If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ }        
        }
    }
}


Function Remove-NectarEndpoint {
    <#
        .SYNOPSIS
        Remove a Nectar DXP endpoint
 
        .DESCRIPTION
        Remove a Nectar DXP endpoint
 
        .PARAMETER ID
        The ID of the endpoint to remove. Both ID and UUID are required for deletion.
         
        .PARAMETER UUID
        The UUID of the endpoint to remove. Both ID and UUID are required for deletion.
         
        .PARAMETER TenantName
        The name of the Nectar DXP tenant. Used in multi-tenant configurations.
         
        .EXAMPLE
        Get-NectarEndpoint -SearchQuery tferguson | Remove-NectarEndpoint
        Removes the endpoint associated with 'tferguson'
         
        .NOTES
        Version 1.0
    #>

    
    Param (
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)]
        [string]$ID,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$True)]
        [string]$UUID,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$TenantName
    )
    
    Begin {
        Connect-NectarCloud

        # Use globally set tenant name, if one was set and not explicitly included in the command
        If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { 
                $TenantName = $Global:NectarTenantName 
            } ElseIf ($TenantName) {
                If ($TenantName -NotIn $Global:NectarTenantList) {
                    $TList = $Global:NectarTenantList -join ', '
                    Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)"
                }
            }
    }        
    Process {
        Try {    
            $URI = "https://$Global:NectarCloud/aapi/testing/entity?id=$ID&uuid=$UUID&tenant=$TenantName"
            Write-Verbose $URI
            
            $NULL = Invoke-RestMethod -Method DELETE -URI $URI -Headers $Global:NectarAuthHeader
        }
        Catch {
            Write-Error "Unable to delete endpoint information. $($_.Exception.Message)"
            If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ }        
        }
    }
}


Function Get-NectarEndpointTest {
    <#
        .SYNOPSIS
        Returns information about Endpoint Client tests
 
        .DESCRIPTION
        Returns information about Endpoint Client tests
        UI_ELEMENT
         
        .PARAMETER TimePeriod
        The time period to show session data from. Select from 'LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','CUSTOM'.
        CUSTOM requires using TimePeriodFrom and TimePeriodTo parameters.
         
        .PARAMETER TimePeriodFrom
        The earliest date/time to show session data from. Must be used in conjunction with -TimePeriod CUSTOM and TimePeriodTo parameters. Use format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'. All time/dates in UTC.
         
        .PARAMETER TimePeriodTo
        The latest date/time to show session data from. Must be used in conjunction with -TimePeriod CUSTOM and TimePeriodFrom parameters. Use format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'. All time/dates in UTC.
         
        .PARAMETER TestTypes
        The types of EPC tests to return. Choose from one or more of 'P2P', 'PING', 'AUDIO', or 'VIDEO'
         
        .PARAMETER TestResults
        The result type to return. Choose from one or more of 'PASSED','FAILED', 'INCOMPLETE' or 'UNKNOWN'
         
        .PARAMETER ResponseCodes
        Show tests that match one or more SIP response codes. Accepts numbers from 0 to 699
         
        .PARAMETER Locations
        Show sessions where the selected location was used by either caller or callee. Can query for multiple locations.
 
        .PARAMETER CallerLocations
        Show sessions where the selected location was used by the caller. Can query for multiple locations.
         
        .PARAMETER CalleeLocations
        Show sessions where the selected location was used by the callee. Can query for multiple locations.
         
        .PARAMETER ExtCities
        Show sessions where the caller or callee was located in the selected city (as detected via geolocating the user's external IP address). Can query for multiple cities.
 
        .PARAMETER CallerExtCities
        Show sessions where the caller was located in the selected city (as detected via geolocating the user's external IP address). Can query for multiple cities.
         
        .PARAMETER CalleeExtCities
        Show sessions where the callee was located in the selected city (as detected via geolocating the user's external IP address). Can query for multiple cities.
         
        .PARAMETER ExtCountries
        Show sessions where the caller or callee was located in the selected country (as detected via geolocating the user's external IP address). Can query for multiple countries.
 
        .PARAMETER CallerExtCountries
        Show sessions where the caller was located in the selected country (as detected via geolocating the user's external IP address). Can query for multiple countries.
         
        .PARAMETER CalleeExtCountries
        Show sessions where the callee was located in the selected country (as detected via geolocating the user's external IP address). Can query for multiple countries.
         
        .PARAMETER ExtISPs
        Show sessions where the caller or callee was located in the selected ISP (as detected via geolocating the user's external IP address). Can query for multiple ISPs.
 
        .PARAMETER CallerExtISPs
        Show sessions where the caller was located in the selected ISP (as detected via geolocating the user's external IP address). Can query for multiple ISPs.
         
        .PARAMETER CalleeExtISPs
        Show sessions where the callee was located in the selected ISP (as detected via geolocating the user's external IP address). Can query for multiple ISPs.
         
        .PARAMETER Users
        Show sessions where the selected user was either caller or callee. Can query for multiple users.
 
        .PARAMETER FromUsers
        Show sessions where the selected user was the caller. Can query for multiple users.
         
        .PARAMETER ToUsers
        Show sessions where the selected user was the callee. Can query for multiple users.
 
        .PARAMETER UserIDs
        Show sessions where the selected user ID was either caller or callee. Can query for multiple user IDs.
 
        .PARAMETER FromUserIDs
        Show sessions where the selected user ID was the caller. Can query for multiple user IDs.
         
        .PARAMETER ToUserIDs
        Show sessions where the selected user ID was the callee. Can query for multiple user IDs.
         
        .PARAMETER OrderByField
        Sort the output by the selected field
         
        .PARAMETER OrderDirection
        Sort direction. Use with OrderByField. Not case sensitive. Choose from:
        ASC, DESC
 
        .PARAMETER TenantName
        The name of the Nectar DXP tenant. Used in multi-tenant configurations.
         
        .PARAMETER PageSize
        The size of the page used to return data. Defaults to 1000
         
        .PARAMETER ResultSize
        The total number of results to return. Defaults to 1000. Maximum result size is 9,999,999 results
         
        .EXAMPLE
        Get-NectarEndpointTest -TimePeriod LAST_HOUR -TestTypes P2P -TestResults FAILED
        Returns a list of all Endpoint Client P2P tests that failed within the last hour
 
        .EXAMPLE
        Get-NectarEndpointTest -TimePeriod LAST_DAY -Locations 'Head Office', Warehouse
        Returns a list of all Endpoint Client tests where either the caller or callee was in the corporate head office or the warehouse
         
        .EXAMPLE
        Get-NectarEndpointTest -TimePeriod LAST_WEEK -CallerExtCities Chicago, Dallas
        Returns a list of all Endpoint Client tests from the last week where the caller was in either Chicago or Dallas
             
        .NOTES
        Version 1.0
    #>

    
    [CmdletBinding(PositionalBinding=$False)]
    Param (
        [Parameter(Mandatory=$False)]
        [ValidateSet('LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','TODAY','YESTERDAY','WEEK_TO_NOW','MONTH_TO_NOW','CUSTOM', IgnoreCase=$True)]
        [string]$TimePeriod = 'LAST_HOUR',
        [Parameter(Mandatory=$False)]
        [Alias("StartDateFrom")]
        [DateTime]$TimePeriodFrom,
        [Parameter(Mandatory=$False)]
        [Alias("StartDateTo")]
        [DateTime]$TimePeriodTo,
        [Parameter(Mandatory=$False)]
        [ValidateSet('P2P','PING','AUDIO','VIDEO', IgnoreCase=$False)]
        [string[]]$TestTypes,    
        [Parameter(Mandatory=$False)]
        [ValidateSet('PASSED','FAILED','UNKNOWN','INCOMPLETE', IgnoreCase=$False)]
        [string[]]$TestResults,
        [Parameter(Mandatory=$False)]
        [ValidateRange(0,699)]
        [string[]]$ResponseCodes,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$Users,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$FromUsers,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ToUsers,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$UserIDs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$FromUserIDs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ToUserIDs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$Locations,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerLocations,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeLocations,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ExtCities,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerExtCities,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeExtCities,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ExtCountries,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerExtCountries,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeExtCountries,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ExtISPs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerExtISPs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeExtISPs,
        [Parameter(Mandatory=$False)]
        [string]$OrderByField,
        [Parameter(Mandatory=$False)]
        [ValidateSet('ASC','DESC', IgnoreCase=$True)]
        [string]$OrderDirection,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$TenantName,
        [Parameter(Mandatory=$False)]
        [ValidateRange(1,10000)]
        [int]$PageSize = 1000,
        [Parameter(Mandatory=$False)]
        [ValidateRange(1,50000)]
        [int]$ResultSize
    )
    
    Process {
        # Use globally set tenant name, if one was set and not explicitly included in the command
        If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { 
                $TenantName = $Global:NectarTenantName 
            } ElseIf ($TenantName) {
                If ($TenantName -NotIn $Global:NectarTenantList) {
                    $TList = $Global:NectarTenantList -join ', '
                    Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)"
                }
            }
        
        If ($PageSize) { $PSBoundParameters.Remove('PageSize') | Out-Null }
        If ($ResultSize) { $PSBoundParameters.Remove('ResultSize') | Out-Null }
        If ($OrderByField) { $PSBoundParameters.Remove('OrderByField') | Out-Null }
        If ($OrderDirection) { $PSBoundParameters.Remove('OrderDirection') | Out-Null }
        
        $FilterSession = Set-NectarFilterParams @PsBoundParameters -Platform ENDPOINT_CLIENT -Scope ENDPOINT_CLIENT
        
        $URI = "https://$Global:NectarCloud/dapi/testing/results"
        Write-Verbose $URI
        
        # Set the page size to the result size if -ResultSize switch is used to limit the number of returned items
        # Otherwise, set page size (defaults to 1000)
        $Params = @{
            'Scope' = 'ENDPOINT_CLIENT'
            'Platform' = 'ENDPOINT_CLIENT'
        }
        
        If ($ResultSize) {
            $Params.Add( 'pageSize',$ResultSize)
        }
        Else {
            $Params.Add('pageSize',$PageSize)
        }
        
        If($OrderByField) { $Params.Add('orderByField',$OrderByField) }
        If($OrderDirection) { $Params.Add('orderDirection',$OrderDirection) }
        If ($TenantName) { $Params.Add('tenant',$TenantName) }
        
        # Return results in pages
        Try {
            Write-Verbose $URI
            ForEach($k in $Params.Keys){Write-Verbose "$k $($Params[$k])"}
            $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader -Body $Params -WebSession $FilterSession
            
            $TotalPages = $JSON.totalPages
            
            If ($TenantName) {$JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty}
            $JSON.elements
            
            If ($TotalPages -gt 1 -and !($ResultSize)) {
                $PageNum = 2
                Write-Verbose "Page size: $PageSize"
                While ($PageNum -le $TotalPages) {
                    Write-Verbose "Working on page $PageNum of $TotalPages"
                    $PagedURI = $URI + "?pageNumber=$PageNum"
                    $JSON = Invoke-RestMethod -Method GET -URI $PagedURI -Headers $Global:NectarAuthHeader -Body $Params -WebSession $FilterSession
                    If ($TenantName) {$JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty}
                    $JSON.elements
                    $PageNum++
                }
            }
        }
        Catch {
            Write-Error "No results. Try specifying a less-restrictive filter. $($_.Exception.Message)"
            If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ }
        }
    }
}


Function Get-NectarEndpointTestSummary {
    <#
        .SYNOPSIS
        Returns summary information about Endpoint Client tests
 
        .DESCRIPTION
        Returns summary information about Endpoint Client tests
        UI_ELEMENT
         
        .PARAMETER TimePeriod
        The time period to show session data from. Select from 'LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','CUSTOM'.
        CUSTOM requires using TimePeriodFrom and TimePeriodTo parameters.
         
        .PARAMETER TimePeriodFrom
        The earliest date/time to show session data from. Must be used in conjunction with -TimePeriod CUSTOM and TimePeriodTo parameters. Use format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'. All time/dates in UTC.
         
        .PARAMETER TimePeriodTo
        The latest date/time to show session data from. Must be used in conjunction with -TimePeriod CUSTOM and TimePeriodFrom parameters. Use format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'. All time/dates in UTC.
         
        .PARAMETER TestTypes
        The types of EPC tests to return. Choose from one or more of 'P2P', 'PING', 'AUDIO', or 'VIDEO'
         
        .PARAMETER TestResults
        The result type to return. Choose from one or more of 'PASSED','FAILED', 'INCOMPLETE' or 'UNKNOWN'
         
        .PARAMETER ResponseCodes
        Show tests that match one or more SIP response codes. Accepts numbers from 0 to 699
         
        .PARAMETER Locations
        Show sessions where the selected location was used by either caller or callee. Can query for multiple locations.
 
        .PARAMETER CallerLocations
        Show sessions where the selected location was used by the caller. Can query for multiple locations.
         
        .PARAMETER CalleeLocations
        Show sessions where the selected location was used by the callee. Can query for multiple locations.
         
        .PARAMETER ExtCities
        Show sessions where the caller or callee was located in the selected city (as detected via geolocating the user's external IP address). Can query for multiple cities.
 
        .PARAMETER CallerExtCities
        Show sessions where the caller was located in the selected city (as detected via geolocating the user's external IP address). Can query for multiple cities.
         
        .PARAMETER CalleeExtCities
        Show sessions where the callee was located in the selected city (as detected via geolocating the user's external IP address). Can query for multiple cities.
         
        .PARAMETER ExtCountries
        Show sessions where the caller or callee was located in the selected country (as detected via geolocating the user's external IP address). Can query for multiple countries.
 
        .PARAMETER CallerExtCountries
        Show sessions where the caller was located in the selected country (as detected via geolocating the user's external IP address). Can query for multiple countries.
         
        .PARAMETER CalleeExtCountries
        Show sessions where the callee was located in the selected country (as detected via geolocating the user's external IP address). Can query for multiple countries.
         
        .PARAMETER ExtISPs
        Show sessions where the caller or callee was located in the selected ISP (as detected via geolocating the user's external IP address). Can query for multiple ISPs.
 
        .PARAMETER CallerExtISPs
        Show sessions where the caller was located in the selected ISP (as detected via geolocating the user's external IP address). Can query for multiple ISPs.
         
        .PARAMETER CalleeExtISPs
        Show sessions where the callee was located in the selected ISP (as detected via geolocating the user's external IP address). Can query for multiple ISPs.
         
        .PARAMETER Users
        Show sessions where the selected user was either caller or callee. Can query for multiple users.
 
        .PARAMETER FromUsers
        Show sessions where the selected user was the caller. Can query for multiple users.
         
        .PARAMETER ToUsers
        Show sessions where the selected user was the callee. Can query for multiple users.
 
        .PARAMETER UserIDs
        Show sessions where the selected user ID was either caller or callee. Can query for multiple user IDs.
 
        .PARAMETER FromUserIDs
        Show sessions where the selected user ID was the caller. Can query for multiple user IDs.
         
        .PARAMETER ToUserIDs
        Show sessions where the selected user ID was the callee. Can query for multiple user IDs.
         
        .PARAMETER OrderByField
        Sort the output by the selected field
         
        .PARAMETER OrderDirection
        Sort direction. Use with OrderByField. Not case sensitive. Choose from:
        ASC, DESC
 
        .PARAMETER TenantName
        The name of the Nectar DXP tenant. Used in multi-tenant configurations.
         
        .PARAMETER PageSize
        The size of the page used to return data. Defaults to 1000
         
        .PARAMETER ResultSize
        The total number of results to return. Defaults to 1000. Maximum result size is 9,999,999 results
         
        .EXAMPLE
        Get-NectarEndpointTestSummary -TimePeriod LAST_HOUR -TestTypes P2P -TestResults FAILED
        Returns a summary of all Endpoint Client P2P tests that failed within the last hour grouped by endpoint
 
        .EXAMPLE
        Get-NectarEndpointTestSummary -TimePeriod LAST_DAY -Locations 'Head Office', Warehouse
        Returns a summary of all Endpoint Client tests grouped by endpoint where either the caller or callee was in the corporate head office or the warehouse
         
        .EXAMPLE
        Get-NectarEndpointTestSummary -TimePeriod LAST_WEEK -CallerExtCities Chicago, Dallas
        Returns a list of all Endpoint Client tests from the last week grouped by endpoint where the caller was in either Chicago or Dallas
             
        .NOTES
        Version 1.0
    #>

    
    [CmdletBinding(PositionalBinding=$False)]
    Param (
        [Parameter(Mandatory=$False)]
        [ValidateSet('LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','TODAY','YESTERDAY','WEEK_TO_NOW','MONTH_TO_NOW','CUSTOM', IgnoreCase=$True)]
        [string]$TimePeriod = 'LAST_HOUR',
        [Parameter(Mandatory=$False)]
        [Alias("StartDateFrom")]
        [DateTime]$TimePeriodFrom,
        [Parameter(Mandatory=$False)]
        [Alias("StartDateTo")]
        [DateTime]$TimePeriodTo,
        [Parameter(Mandatory=$False)]
        [ValidateSet('P2P','PING','AUDIO','VIDEO', IgnoreCase=$False)]
        [string[]]$TestTypes,    
        [Parameter(Mandatory=$False)]
        [ValidateSet('PASSED','FAILED','UNKNOWN','INCOMPLETE','INCOMPLETE', IgnoreCase=$False)]
        [string[]]$TestResults,
        [Parameter(Mandatory=$False)]
        [ValidateSet('HUB','ENDPOINT', IgnoreCase=$False)]
        [string]$HubOrEndpoint = 'ENDPOINT',
        [Parameter(Mandatory=$False)]
        [ValidateRange(0,699)]
        [string[]]$ResponseCodes,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$Users,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$FromUsers,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ToUsers,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$UserIDs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$FromUserIDs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ToUserIDs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$Locations,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerLocations,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeLocations,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ExtCities,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerExtCities,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeExtCities,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ExtCountries,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerExtCountries,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeExtCountries,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ExtISPs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerExtISPs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeExtISPs,
        [Parameter(Mandatory=$False)]
        [ValidateSet('displayName','testSuccessRate','testCount', IgnoreCase=$True)]
        [string]$OrderByField,
        [Parameter(Mandatory=$False)]
        [ValidateSet('ASC','DESC', IgnoreCase=$True)]
        [string]$OrderDirection,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$TenantName,
        [Parameter(Mandatory=$False)]
        [ValidateRange(1,10000)]
        [int]$PageSize = 1000,
        [Parameter(Mandatory=$False)]
        [ValidateRange(1,50000)]
        [int]$ResultSize
    )
    
    Process {
        # Use globally set tenant name, if one was set and not explicitly included in the command
        If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { 
                $TenantName = $Global:NectarTenantName 
            } ElseIf ($TenantName) {
                If ($TenantName -NotIn $Global:NectarTenantList) {
                    $TList = $Global:NectarTenantList -join ', '
                    Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)"
                }
            }

        If ($HubOrEndpoint) { $PSBoundParameters.Remove('HubOrEndpoint') | Out-Null }
        If ($PageSize) { $PSBoundParameters.Remove('PageSize') | Out-Null }
        If ($ResultSize) { $PSBoundParameters.Remove('ResultSize') | Out-Null }
        If ($OrderByField) { $PSBoundParameters.Remove('OrderByField') | Out-Null }
        If ($OrderDirection) { $PSBoundParameters.Remove('OrderDirection') | Out-Null }
        
        $FilterSession = Set-NectarFilterParams @PsBoundParameters -Platform ENDPOINT_CLIENT -Scope ENDPOINT_CLIENT
        
        $URI = "https://$Global:NectarCloud/dapi/testing/entities"
        Write-Verbose $URI
        
        # Set the page size to the result size if -ResultSize switch is used to limit the number of returned items
        # Otherwise, set page size (defaults to 1000)
        $Params = @{
            'Platform' = 'ENDPOINT_CLIENT'
            'type' = $HubOrEndpoint
        }
        
        If ($ResultSize) {
            $Params.Add( 'pageSize',$ResultSize)
        }
        Else {
            $Params.Add('pageSize',$PageSize)
        }
        
        If($OrderByField) { $Params.Add('orderByField',$OrderByField) }
        If($OrderDirection) { $Params.Add('orderDirection',$OrderDirection) }
        If ($TenantName) { $Params.Add('tenant',$TenantName) }
        
        # Return results in pages
        Try {
            Write-Verbose $URI
            foreach($k in $Params.Keys){Write-Verbose "$k $($Params[$k])"}
            $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader -Body $Params -WebSession $FilterSession
            
            $TotalPages = $JSON.totalPages
            
            If ($TenantName) {$JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty}
            $JSON.elements
            
            If ($TotalPages -gt 1 -and !($ResultSize)) {
                $PageNum = 2
                Write-Verbose "Page size: $PageSize"
                While ($PageNum -le $TotalPages) {
                    Write-Verbose "Working on page $PageNum of $TotalPages"
                    $PagedURI = $URI + "?pageNumber=$PageNum"
                    $JSON = Invoke-RestMethod -Method GET -URI $PagedURI -Headers $Global:NectarAuthHeader -Body $Params -WebSession $FilterSession
                    If ($TenantName) {$JSON.elements | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty}
                    $JSON.elements
                    $PageNum++
                }
            }
        }
        Catch {
            Write-Error "No results. Try specifying a less-restrictive filter. $($_.Exception.Message)"
            If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ }
        }
    }
}


Function Get-NectarEndpointTestCount {
    <#
        .SYNOPSIS
        Returns summary information about Endpoint Client tests
 
        .DESCRIPTION
        Returns summary information about Endpoint Client tests
        UI_ELEMENT
         
        .PARAMETER TimePeriod
        The time period to show session data from. Select from 'LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','CUSTOM'.
        CUSTOM requires using TimePeriodFrom and TimePeriodTo parameters.
         
        .PARAMETER TimePeriodFrom
        The earliest date/time to show session data from. Must be used in conjunction with -TimePeriod CUSTOM and TimePeriodTo parameters. Use format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'. All time/dates in UTC.
         
        .PARAMETER TimePeriodTo
        The latest date/time to show session data from. Must be used in conjunction with -TimePeriod CUSTOM and TimePeriodFrom parameters. Use format 'YYYY-MM-DD' or 'YYYY-MM-DD HH:MM:SS'. All time/dates in UTC.
         
        .PARAMETER TestTypes
        The types of EPC tests to return. Choose from one or more of 'P2P', 'PING', 'AUDIO', or 'VIDEO'
         
        .PARAMETER TestResults
        The result type to return. Choose from one or more of 'PASSED','FAILED', 'INCOMPLETE' or 'UNKNOWN'
         
        .PARAMETER ResponseCodes
        Show tests that match one or more SIP response codes. Accepts numbers from 0 to 699
         
        .PARAMETER Locations
        Show sessions where the selected location was used by either caller or callee. Can query for multiple locations.
 
        .PARAMETER CallerLocations
        Show sessions where the selected location was used by the caller. Can query for multiple locations.
         
        .PARAMETER CalleeLocations
        Show sessions where the selected location was used by the callee. Can query for multiple locations.
         
        .PARAMETER ExtCities
        Show sessions where the caller or callee was located in the selected city (as detected via geolocating the user's external IP address). Can query for multiple cities.
 
        .PARAMETER CallerExtCities
        Show sessions where the caller was located in the selected city (as detected via geolocating the user's external IP address). Can query for multiple cities.
         
        .PARAMETER CalleeExtCities
        Show sessions where the callee was located in the selected city (as detected via geolocating the user's external IP address). Can query for multiple cities.
         
        .PARAMETER ExtCountries
        Show sessions where the caller or callee was located in the selected country (as detected via geolocating the user's external IP address). Can query for multiple countries.
 
        .PARAMETER CallerExtCountries
        Show sessions where the caller was located in the selected country (as detected via geolocating the user's external IP address). Can query for multiple countries.
         
        .PARAMETER CalleeExtCountries
        Show sessions where the callee was located in the selected country (as detected via geolocating the user's external IP address). Can query for multiple countries.
         
        .PARAMETER ExtISPs
        Show sessions where the caller or callee was located in the selected ISP (as detected via geolocating the user's external IP address). Can query for multiple ISPs.
 
        .PARAMETER CallerExtISPs
        Show sessions where the caller was located in the selected ISP (as detected via geolocating the user's external IP address). Can query for multiple ISPs.
         
        .PARAMETER CalleeExtISPs
        Show sessions where the callee was located in the selected ISP (as detected via geolocating the user's external IP address). Can query for multiple ISPs.
         
        .PARAMETER Users
        Show sessions where the selected user was either caller or callee. Can query for multiple users.
 
        .PARAMETER FromUsers
        Show sessions where the selected user was the caller. Can query for multiple users.
         
        .PARAMETER ToUsers
        Show sessions where the selected user was the callee. Can query for multiple users.
 
        .PARAMETER UserIDs
        Show sessions where the selected user ID was either caller or callee. Can query for multiple user IDs.
 
        .PARAMETER FromUserIDs
        Show sessions where the selected user ID was the caller. Can query for multiple user IDs.
         
        .PARAMETER ToUserIDs
        Show sessions where the selected user ID was the callee. Can query for multiple user IDs.
         
        .PARAMETER OrderByField
        Sort the output by the selected field
         
        .PARAMETER OrderDirection
        Sort direction. Use with OrderByField. Not case sensitive. Choose from:
        ASC, DESC
 
        .PARAMETER TenantName
        The name of the Nectar DXP tenant. Used in multi-tenant configurations.
         
        .PARAMETER PageSize
        The size of the page used to return data. Defaults to 1000
         
        .PARAMETER ResultSize
        The total number of results to return. Defaults to 1000. Maximum result size is 9,999,999 results
         
        .EXAMPLE
        Get-NectarEndpointTestCount -TimePeriod LAST_HOUR -TestTypes P2P -TestResults FAILED
        Returns a count of all Endpoint Client P2P tests that failed within the last hour
 
        .EXAMPLE
        Get-NectarEndpointTestCount -TimePeriod LAST_DAY -Locations 'Head Office', Warehouse
        Returns a count of all Endpoint Client tests where either the caller or callee was in the corporate head office or the warehouse
         
        .EXAMPLE
        Get-NectarEndpointTestSummary -TimePeriod LAST_WEEK -CallerExtCities Chicago, Dallas
        Returns a count of all Endpoint Client tests from the last week where the caller was in either Chicago or Dallas
             
        .NOTES
        Version 1.0
    #>

    
    [CmdletBinding(PositionalBinding=$False)]
    Param (
        [Parameter(Mandatory=$False)]
        [ValidateSet('LAST_HOUR','LAST_DAY','LAST_WEEK','LAST_MONTH','TODAY','YESTERDAY','WEEK_TO_NOW','MONTH_TO_NOW','CUSTOM', IgnoreCase=$True)]
        [string]$TimePeriod = 'LAST_HOUR',
        [Parameter(Mandatory=$False)]
        [Alias("StartDateFrom")]
        [DateTime]$TimePeriodFrom,
        [Parameter(Mandatory=$False)]
        [Alias("StartDateTo")]
        [DateTime]$TimePeriodTo,
        [Parameter(Mandatory=$False)]
        [ValidateSet('P2P','PING','AUDIO','VIDEO', IgnoreCase=$False)]
        [string[]]$TestTypes,    
        [Parameter(Mandatory=$False)]
        [ValidateSet('PASSED','FAILED','UNKNOWN','INCOMPLETE','INCOMPLETE', IgnoreCase=$False)]
        [string[]]$TestResults,
        [Parameter(Mandatory=$False)]
        [ValidateSet('HUB','ENDPOINT', IgnoreCase=$False)]
        [string]$HubOrEndpoint = 'ENDPOINT',
        [Parameter(Mandatory=$False)]
        [ValidateRange(0,699)]
        [string[]]$ResponseCodes,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$Users,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$FromUsers,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ToUsers,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$UserIDs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$FromUserIDs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ToUserIDs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$Locations,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerLocations,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeLocations,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ExtCities,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerExtCities,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeExtCities,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ExtCountries,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerExtCountries,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeExtCountries,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$ExtISPs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CallerExtISPs,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string[]]$CalleeExtISPs,
        [Parameter(Mandatory=$False)]
        [ValidateSet('ASC','DESC', IgnoreCase=$True)]
        [string]$OrderDirection,
        [Parameter(ValueFromPipelineByPropertyName, Mandatory=$False)]
        [string]$TenantName
    )
    
    Process {
        # Use globally set tenant name, if one was set and not explicitly included in the command
        If ($Global:NectarTenantName -And !$PSBoundParameters.ContainsKey('TenantName')) { 
                $TenantName = $Global:NectarTenantName 
            } ElseIf ($TenantName) {
                If ($TenantName -NotIn $Global:NectarTenantList) {
                    $TList = $Global:NectarTenantList -join ', '
                    Throw "Could not find a tenant with the name $TenantName on https://$Global:NectarCloud. Select one of $TList. $($_.Exception.Message)"
                }
            }

        If ($HubOrEndpoint) { $PSBoundParameters.Remove('HubOrEndpoint') | Out-Null }
        
        $FilterSession = Set-NectarFilterParams @PsBoundParameters -Platform ENDPOINT_CLIENT -Scope ENDPOINT_CLIENT
        
        $URI = "https://$Global:NectarCloud/dapi/testing/counts"
        Write-Verbose $URI
        
        # Set the page size to the result size if -ResultSize switch is used to limit the number of returned items
        # Otherwise, set page size (defaults to 1000)
        $Params = @{
            'platform' = 'ENDPOINT_CLIENT'
            'tenant' = $TenantName
        }
        
        Try {
            Write-Verbose $URI
            foreach($k in $Params.Keys){Write-Verbose "$k $($Params[$k])"}
            $JSON = Invoke-RestMethod -Method GET -URI $URI -Headers $Global:NectarAuthHeader -Body $Params -WebSession $FilterSession
            
            If ($TenantName) {$JSON | Add-Member -Name 'TenantName' -Value $TenantName -MemberType NoteProperty}
            Return $JSON
        }
        Catch {
            Write-Error "No results. Try specifying a less-restrictive filter. $($_.Exception.Message)"
            If ($PSCmdlet.MyInvocation.BoundParameters["ErrorAction"] -ne "SilentlyContinue") { Get-JSONErrorStream -JSONResponse $_ }
        }
    }
}