Public/VoiceConfig/Get-TeamsVoiceRoutingChain.ps1
# Module: TeamsFunctions # Function: Tenant Voice Configuration # Author: David Eberhardt # Updated: 19-FEB-2022 # Status: Live function Get-TeamsVoiceRoutingChain { <# .SYNOPSIS Queries an Online Voice Routing Policy and all associated Objects dependent on configuration .DESCRIPTION Returns a custom object detailing voice routing chain .PARAMETER Object CsOnlineVoiceRoutingPolicy Object. Identifying the Online Voice Routing Policy Required to identify the correct OVP and start the determination chain .PARAMETER Identity String. Name (Identity) of the Online Voice Routing Policy Required to identify the correct OVP and start the determination chain .PARAMETER Detailed Optional Switch. Displays nested Objects for all Elements of the Voice Routing Chain By default, only Names of nested Objects are shown. .EXAMPLE Get-TeamsVoiceRoutingChain -Identity "OVP-AMER-GSIP-MX" Queries the Online Voice Routing Policy OVP-AMER-GSIP-MX and determines the Chain. Determines Pstn Usages nested in this Policy and Voice Routes that reference this Pstn Usage. .EXAMPLE Get-TeamsVoiceRoutingChain -Identity "OVP-AMER-GSIP-MX" -Detailed Queries the Online Voice Routing Policy OVP-AMER-GSIP-MX and determines the Chain. Determines Pstn Usages nested in this Policy and Voice Routes that reference this Pstn Usage. Displays a tree object for the whole chain .EXAMPLE Get-TeamsVoiceRoutingChain -Identity $CsOnlineVoiceRoutingPolicy Queries the Online Voice Routing Policy Identified in the $CsOnlineVoiceRoutingPolicy Object and determines the Chain. Determines Pstn Usages nested in this Policy and Voice Routes that reference this Pstn Usage. .EXAMPLE $CsOnlineVoiceRoutingPolicy | Get-TeamsVoiceRoutingChain Queries the Online Voice Routing Policy Identified in the $CsOnlineVoiceRoutingPolicy Object and determines the Chain. Determines Pstn Usages nested in this Policy and Voice Routes that reference this Pstn Usage. .INPUTS System.String System.Object .OUTPUTS System.Object .NOTES Sister CmdLet to Find-TeamsUserVoiceRoute that focuses on determining a Route for a Call dependent on the dialled number .COMPONENT Tenant Voice Routing .FUNCTIONALITY Direct Routing .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/Get-TeamsVoiceRoutingChain.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/Find-TeamsUserVoiceRoute.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/Find-TeamsEmergencyCallRoute.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/about_VoiceConfiguration.md .LINK https://github.com/DEberhardt/TeamsFunctions/tree/main/docs/ #> [CmdletBinding(DefaultParameterSetName = 'Name', ConfirmImpact = 'Low')] [Alias('Get-TeamsVRC')] [OutputType([PSCustomObject])] param( #TEST Whether both Object and Identity work - replicate for Set-TeamsCAP [Parameter(Mandatory, Position = 0, ParameterSetName = 'Object', ValueFromPipeline)] [Object[]]$Object, [Parameter(Mandatory, Position = 0, ParameterSetName = 'Name', ValueFromPipeline, HelpMessage = 'Name of the Online Voice Routing Policy')] [ValidateScript( { if ($_ -in $(&$global:TfAcSbVoiceRoutingPolicy)) { return $true } else { throw [System.Management.Automation.ValidationMetadataException] 'Value must be a valid Policy in the Tenant. Use Intellisense for options' } })] [ArgumentCompleter({ &$global:TfAcSbVoiceRoutingPolicy })] [string[]]$Identity, [switch]$Detailed ) begin { Show-FunctionStatus -Level Live Write-Verbose -Message "[BEGIN ] $($MyInvocation.MyCommand.Name)" Write-Verbose -Message "Need help? Online: $global:TeamsFunctionsHelpURLBase$($MyInvocation.MyCommand.Name)`.md" # Asserting MicrosoftTeams Connection if ( -not (Assert-MicrosoftTeamsConnection) ) { break } # Setting Preference Variables according to Upstream settings if (-not $PSBoundParameters.ContainsKey('Verbose')) { $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') } if (-not $PSBoundParameters.ContainsKey('Confirm')) { $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') } if (-not $PSBoundParameters.ContainsKey('WhatIf')) { $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') } if (-not $PSBoundParameters.ContainsKey('Debug')) { $DebugPreference = $PSCmdlet.SessionState.PSVariable.GetValue('DebugPreference') } else { $DebugPreference = 'Continue' } if ( $PSBoundParameters.ContainsKey('InformationAction')) { $InformationPreference = $PSCmdlet.SessionState.PSVariable.GetValue('InformationAction') } else { $InformationPreference = 'Continue' } #region Defining Output Object class TFVoiceRoutingChain { [string]$OnlineVoiceRoutingPolicy $OnlinePstnUsageList $OnlineVoiceRouteList $OnlinePstnGatewayList [String]$NumberPattern hidden [System.Collections.Generic.List[object]]$VoiceRoutingChain TFVoiceRoutingChain( [string]$OnlineVoiceRoutingPolicy, $OnlinePstnUsageList, $OnlineVoiceRouteList, $OnlinePstnGatewayList, $NumberPattern ) { $this.OnlineVoiceRoutingPolicy = $OnlineVoiceRoutingPolicy $this.OnlinePstnUsageList = $OnlinePstnUsageList $this.OnlineVoiceRouteList = $OnlineVoiceRouteList $this.OnlinePstnGatewayList = $OnlinePstnGatewayList $this.NumberPattern = $NumberPattern } } #endregion # Preparing Splatting Object $Parameters = $null $Parameters = @{ 'Detailed' = ($Detailed) } #Worker functions Function GetVoiceRoutingChain { [CmdletBinding()] param( [Parameter(Mandatory)] [object]$Object, [switch]$Detailed ) # Setting Preference Variables according to Upstream settings if (-not $PSBoundParameters.ContainsKey('Verbose')) { $VerbosePreference = $PSCmdlet.SessionState.PSVariable.GetValue('VerbosePreference') } if (-not $PSBoundParameters.ContainsKey('Confirm')) { $ConfirmPreference = $PSCmdlet.SessionState.PSVariable.GetValue('ConfirmPreference') } if (-not $PSBoundParameters.ContainsKey('WhatIf')) { $WhatIfPreference = $PSCmdlet.SessionState.PSVariable.GetValue('WhatIfPreference') } if (-not $PSBoundParameters.ContainsKey('Debug')) { $DebugPreference = $PSCmdlet.SessionState.PSVariable.GetValue('DebugPreference') } else { $DebugPreference = 'Continue' } if ( $PSBoundParameters.ContainsKey('InformationAction')) { $InformationPreference = $PSCmdlet.SessionState.PSVariable.GetValue('InformationAction') } else { $InformationPreference = 'Continue' } Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" # Voice Routing $VoiceRoutingChain = [TFVoiceRoutingChain]::new($Object.Identity, $null, $null, $null, $null) if ($PSBoundParameters.ContainsKey('Debug') -or $DebugPreference -eq 'Continue') { "Function: $($MyInvocation.MyCommand.Name) - CsOnlineVoiceRoutingPolicy", ( $Object | Format-List | Out-String).Trim() | Write-Debug } Write-Verbose -Message "Online Voice Routing Policy '$($Object.Identity)'" $OPUs = $null $OPUs = $Object.OnlinePstnUsages if ($PSBoundParameters.ContainsKey('Debug') -or $DebugPreference -eq 'Continue') { "Function: $($MyInvocation.MyCommand.Name) - PSTN Usages: $($OPUs -join ', ')" | Write-Debug } if ($OPUs) { Write-Verbose -Message 'Online Pstn Usage' [System.Collections.Generic.List[object]]$OPUObjects = @() foreach ($OPU in $OPUs) { Write-Verbose -Message "Online Pstn Usage '$OPU'" $Routes += Get-CsOnlineVoiceRoute | Where-Object { $_.OnlinePstnUsages -contains $OPU } | Select-Object *, @{label = 'PSTNUsage'; Expression = { $OPU } } [System.Collections.Generic.List[object]]$VoiceRoutes = @() [System.Collections.Generic.List[object]]$OVRObjects = @() foreach ($Route in $Routes) { Write-Verbose -Message "Online Pstn Usage '$OPU' - Online Voice Route '$($Route.Name)'" if ( $VoiceRoutes -notcontains $Route ) { [void]$VoiceRoutes.Add($Route) } if ( $Detailed ) { [System.Collections.Generic.List[object]]$MGWObjects = @() foreach ($Gateway in $Route.OnlinePstnGatewayList) { Write-Verbose -Message "Online Pstn Usage '$OPU' - Online Voice Route '$($Route.Name)' - Gateway '$($Gateway.Identity)'" $CsOnlinePSTNGateway = Get-CsOnlinePSTNGateway $Gateway $MGWObject = Merge-VoiceRoutingChainArtefact -Type MGW -Object $CsOnlinePSTNGateway if ( $MGWObjects.Identity -notcontains $MGWObject.Identity ) { [void]$MGWObjects.Add($MGWObject) } } $OVRObject = Merge-VoiceRoutingChainArtefact -Type OVR -Object $Route -MGWs $MGWObjects if ( $OVRObjects.Name -notcontains $OVRObject.Name ) { [void]$OVRObjects.Add($OVRObject) } } } if ($PSBoundParameters.ContainsKey('Debug') -or $DebugPreference -eq 'Continue') { "Function: $($MyInvocation.MyCommand.Name) - VoiceRoutes", ( $VoiceRoutes | Format-List | Out-String).Trim() | Write-Debug } $VoiceRoutingChain.OnlinePstnUsageList = $Object.OnlinePstnUsages if ( $VoiceRoutes ) { $VoiceRoutingChain.OnlineVoiceRouteList = $VoiceRoutes.Identity $VoiceRoutingChain.OnlinePstnGatewayList = $VoiceRoutes.OnlinePstnGatewayList $VoiceRoutingChain.NumberPattern = $VoiceRoutes.NumberPattern } else { Write-Warning -Message "OVP '$($Object.Identity)' - No Online Voice Routes have been found" } if ( $Detailed ) { Write-Verbose -Message 'Creating Voice Routing Chain Object' $OPUObject = Merge-VoiceRoutingChainArtefact -Type OPU -Object $OPU -OVRs $OVRObjects if ( $OPUObjects -notcontains $OPUObject ) { [void]$OPUObjects.Add($OPUObject) } #Adding Chained Object to Parent $VoiceRoutingChain.VoiceRoutingChain = $OPUObjects } } } else { Write-Warning -Message "OVP '$($Object.Identity)' - No Online PSTN Usages have been found" } if ( $Detailed ) { Write-Output $VoiceRoutingChain | Select-Object OnlineVoiceRoutingPolicy, OnlinePstnUsageList, OnlineVoiceRouteList, OnlinePstnGatewayList, NumberPattern, VoiceRoutingChain } else { Write-Output $VoiceRoutingChain } } } Process { Write-Verbose -Message "[PROCESS] $($MyInvocation.MyCommand)" switch ($PSCmdlet.ParameterSetName) { 'Name' { foreach ($Id in $Identity) { Write-Verbose -Message "[PROCESS] Processing '$Id'" try { if ($Id -match [regex]::Escape('*')) { $CsOnlineVoiceRoutingPolicy = Get-CsOnlineVoiceRoutingPolicy -Filter "*$Id*"-WarningAction SilentlyContinue -ErrorAction Stop } else { $CsOnlineVoiceRoutingPolicy = Get-CsOnlineVoiceRoutingPolicy -Identity "$Id"-WarningAction SilentlyContinue -ErrorAction Stop } } catch { Write-Error "CsOnlineVoiceRoutingPolicy '$Id' not found" -Category ObjectNotFound continue } foreach ($O in $CsOnlineVoiceRoutingPolicy) { Write-Verbose -Message "[PROCESS] Processing Found '$($O.Identity)'" GetVoiceRoutingChain -Object $O @Parameters @Args } } } 'Object' { foreach ($O in $Object) { Write-Verbose -Message "[PROCESS] Processing provided CsOnlineVoiceRoutingPolicy Object for '$($O.Identity)'" GetVoiceRoutingChain -Object $O @Parameters @Args } } } } end { Write-Verbose -Message "[END ] $($MyInvocation.MyCommand)" } } # Get-TeamsVoiceRoutingChain |