PagerDutyAutomation.psm1
#Requires -Version 5.1 Set-StrictMode -Version 'Latest' # Functions should use $moduleRoot as the relative root from which to find # things. A published module has its function appended to this file, while a # module in development has its functions in the Functions directory. $moduleRoot = $PSScriptRoot # Store each of your module's functions in its own file in the Functions # directory. On the build server, your module's functions will be appended to # this file, so only dot-source files that exist on the file system. This allows # developers to work on a module without having to build it first. Grab all the # functions that are in their own files. $functionsPath = Join-Path -Path $moduleRoot -ChildPath 'Functions\*.ps1' if( (Test-Path -Path $functionsPath) ) { foreach( $functionPath in (Get-Item $functionsPath) ) { . $functionPath.FullName } } function Invoke-PDRestMethod { <# .SYNOPSIS Calls endpoints on the PagerDuty API. .DESCRIPTION The `Invoke-PDRestMethod` calls an endpoint on the PagerDuty API. Pass the session to use to the `Session` parameter (create a session with the `New-PDSession` function). Pass the path to the endpoint to the `Path` parameter. If the endpoint returns paged results, `Invoke-PDRestMethod` will return an object for the first page of results. The return object will have these properties (see https://developer.pagerduty.com/docs/rest-api-v2/pagination/): * `limit`, which is the number of objects returned. * `offset`, which is the index of the first item in the results across all pages. * `more`, which is `$true` if there are more results and `$false` otherwise. * `total`, which is `$null` by default. If you want to know the total number of records across all pages, use the `IncludeTotal` parameter, and then this property will be the total number of objects. Use the `Offset` parameter to control the start index of the records to return. Use the `Count` parameter to control how many records to return in each request. If you don't want to paginate, use the `All` parameter to return all records. If you want to find a specific item, you can pass a script block expression to the `First` parameter. `Invoke-PDRestMethod` will return the first object that returns `$true` when passed through that filter using `Where-Object`. `Invoke-PDRestMethod` will automatically page through results until it finds an item and stops making requests once the object is found. If you want to return all items that match an expression, pass the expression as a script block to the `Filter` parameter. `Invoke-PDRestMethod` will page through all results and return objects that return `$true` when passed to the script block using the `Where-Object` cmdlet. If you have the full URL to an item (usually from the `self` property on an object returned by an endpoint), you can pass that to the `Uri` parameter. If you're calling an endpoint that receives a JSON body, pass the JSON to the `Body` parameter. You can also pass in an object, and `Invoke-PDRestMethod` will convert it to JSON for you (e.g. `$Body | ConvertTo-Json -Depth 50`). Use the `Method` parameter to use the correct REST verb. .EXAMPLE $page = Invoke-PDRestMethod -Session $session -Path 'services' Demonstrates how to use `Invoke-PDRestMethod` to get a single page of records. .EXAMPLE $page2 = Invoke-PDRestMethod -Session $session -Path 'services' -Offset 25 Demonstrates how to get a different page of results using the `Offset` parameter. .EXAMPLE $page = Invoke-PDRestMethod -Session $session -Path 'services' -Count 100 Demonstrates how to increase the number of records returned by each request using the `Count` parameter. .EXAMPLE $services = Invoke-PDRestMethod -Session $session -Path 'services' -All Demonstrates how to use the `All` parameter to skip paging the results and return all objects. .EXAMPLE $page = Invoke-PDRestMethod -Session $session -path 'services' -IncludeTotal Demonstrates how to use the `IncludeTotal` parameter to include the total number of results across all pages in the return object. .EXAMPLE Invoke-PDRestMethod -Session $session -Path 'services' -First { $_.name -eq 'My Service' } Demonstrates how to use the `First` parameter to return the first item that gets selected by a script block. The script block is passed to `Where-Object` to select the object to return. Once an object is found, no further requests are made to PagerDuty. .EXAMPLE Invoke-PDRestMethod -Session $session -Path 'services' -Filter { $_.name -like '*filter*' } Demonstrates how to use the `Filter` parameter to return all items that are selected by a script block. The script block is passed to `Where-Object` to select the objects to return. .EXAMPLE Invoke-PDRestMethod -Session $session -Uri $item.self Demonstrates how to use the full `self` URLs returned on PagerDuty objects to get specific objects. .EXAMPLE Invoke-PDRestMethod -Session $session -Path 'services' -Body $json -Method Post Demonstrates how to create an item by passing the new object's JSON to the `Body` parameter. .EXAMPLE Invoke-PDRestMethod -Session $session -Path 'services' -Body $newService -Method Post Demonstrates how to create an item by passing an object to the `Body` parameter. The `Invoke-PDRestMethod` function converts the object to JSON using `ConvertTo-Json`. #> [CmdletBinding(DefaultParameterSetName='Pagination')] param( [Parameter(Mandatory)] [Object]$Session, [Parameter(Mandatory,ParameterSetName='Uri')] [Uri]$Uri, [Parameter(Mandatory,ParameterSetName='Pagination')] [Parameter(Mandatory,ParameterSetName='First')] [Parameter(Mandatory,ParameterSetName='Filter')] [Parameter(Mandatory,ParameterSetName='All')] [String]$Path, [Microsoft.PowerShell.Commands.WebRequestMethod]$Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get, [Object]$Body, [Parameter(ParameterSetName='Pagination')] [int]$Offset, [Parameter(ParameterSetName='Pagination')] [int]$Count, [Parameter(ParameterSetName='Pagination')] [switch]$IncludeTotal, [Parameter(ParameterSetName='First')] [scriptblock]$First, [Parameter(ParameterSetName='Filter')] [scriptblock]$Filter, [Parameter(ParameterSetName='All')] [switch]$All ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if( $PSCmdlet.ParameterSetName -in @('First', 'Filter', 'All') ) { $parameters = [Collections.Generic.Dictionary[String,Object]]::New($PSBoundParameters) [void]$parameters.Remove('First') [void]$parameters.Remove('Filter') [void]$parameters.Remove('All') $resultPropertyName = $null $startAt = 0 do { $page = Invoke-PDRestMethod @parameters -Offset $startAt -Count 1000 $startAt += $page.limit # The property holding the return objects is different across endpoints. if( -not $resultPropertyName ) { $propertyNames = $page | Get-Member -MemberType 'NoteProperty' | Select-Object -ExpandProperty 'Name' foreach( $propertyName in $propertyNames ) { $propertyType = $page.$propertyName.GetType() if( $propertyType.IsArray ) { $resultPropertyName = $propertyName break } } } $results = $page.$resultPropertyName | Where-Object { if( $First ) { $_ | Where-Object $First } if( $Filter ) { $_ | Where-Object $Filter } if( $All ) { return $true } } if( $First -and $results ) { return $results | Select-Object -First 1 | Write-Output } $results | Write-Output } while( $page.more ) return } $headers = @{ 'Authorization' = "Token token=$($Session.Token)"; 'Accept' = 'application/vnd.pagerduty+json;version=2'; } $url = $null if( $PSCmdlet.ParameterSetName -eq 'Uri' ) { $url = $Uri.ToString() } else { $queryString = & { if( $Offset ) { "offset=$($Offset)" | Write-Output } if( $IncludeTotal ) { "total=true" | Write-Output } if( $Count ) { "limit=$($Count)" | Write-Output } } if( $queryString ) { $queryString = "?$($queryString -join '&')" } $url = "$($Session.Url)/$($Path.TrimStart('/'))$($queryString)" } $conditionalParams = @{} if( $Body ) { if( $Body -is [string] ) { $conditionalParams['Body'] = $Body } else { $conditionalParams['Body'] = $Body | ConvertTo-Json -Depth 50 } } $result = $null try { $result = Invoke-RestMethod -Uri $url ` -Headers $headers ` -ContentType 'application/json' ` -Method $Method ` @conditionalParams } catch { $pderror = $_.ErrorDetails | ConvertFrom-Json $response = $_.Exception.Response $httpStatusDesc = & { if( $response | Get-Member -Name 'ReasonPhrase' ) { return $response.ReasonPhrase } return $response.StatusDescription } $httpStatusCode = $_.Exception.Response.StatusCode $msg = "Request to $($url) failed with HTTP error ""$($httpStatusDesc)"" ($([int]$httpStatusCode))." $pdErrMsg = $pderror | Select-Object -ExpandProperty 'error' -ErrorAction Ignore | Select-Object -ExpandProperty 'message' -ErrorAction Ignore $pdErrCode = $pderror | Select-Object -ExpandProperty 'error' -ErrorAction Ignore | Select-Object -ExpandProperty 'code' -ErrorAction Ignore if ($pdErrMsg) { $msg = "$($msg) PagerDuty error ""$($pdErrMsg)"" ($($pdErrCode)))." $pdErrList = $pderror.error | Select-Object -ExpandProperty 'errors' -ErrorAction Ignore if ($pdErrList) { $msg = "$($msg) $($pdErrList -join '. ')." } } Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } if( -not $result ) { return } if( -not ($result | Get-Member -Name 'offset') ) { $objectPropertyName = $result | Get-Member -MemberType NoteProperty | Select-Object -First 1 | Select-Object -ExpandProperty 'Name' return $result | Select-Object -ExpandProperty $objectPropertyName } return $result } function New-PDSession { <# .SYNOPSIS Creates a PagerDutyAutomation session object. .DESCRIPTION The `New-PDSession` function creates a PagerDutyAutomation session object. This object contains the API token and the URL to the PagerDuty API to use. This object should be passed to all PagerDutyAutomation commands. .EXAMPLE $session = New-PDSession -Token 'my_secret_token' Demonstrates how to create a PagerDutyAutomation session object. #> [CmdletBinding()] param( [Parameter(Mandatory)] [String]$Token ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState return [pscustomobject]@{ 'Token' = $Token; 'Url' = 'https://api.pagerduty.com'; } } # Copyright 2012 Aaron Jensen # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. function Use-CallerPreference { <# .SYNOPSIS Sets the PowerShell preference variables in a module's function based on the callers preferences. .DESCRIPTION Script module functions do not automatically inherit their caller's variables, including preferences set by common parameters. This means if you call a script with switches like `-Verbose` or `-WhatIf`, those that parameter don't get passed into any function that belongs to a module. When used in a module function, `Use-CallerPreference` will grab the value of these common parameters used by the function's caller: * ErrorAction * Debug * Confirm * InformationAction * Verbose * WarningAction * WhatIf This function should be used in a module's function to grab the caller's preference variables so the caller doesn't have to explicitly pass common parameters to the module function. This function is adapted from the [`Get-CallerPreference` function written by David Wyatt](https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d). There is currently a [bug in PowerShell](https://connect.microsoft.com/PowerShell/Feedback/Details/763621) that causes an error when `ErrorAction` is implicitly set to `Ignore`. If you use this function, you'll need to add explicit `-ErrorAction $ErrorActionPreference` to every function/cmdlet call in your function. Please vote up this issue so it can get fixed. .LINK about_Preference_Variables .LINK about_CommonParameters .LINK https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d .LINK http://powershell.org/wp/2014/01/13/getting-your-script-module-functions-to-inherit-preference-variables-from-the-caller/ .EXAMPLE Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState Demonstrates how to set the caller's common parameter preference variables in a module function. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] #[Management.Automation.PSScriptCmdlet] # The module function's `$PSCmdlet` object. Requires the function be decorated with the `[CmdletBinding()]` attribute. $Cmdlet, [Parameter(Mandatory = $true)] [Management.Automation.SessionState] # The module function's `$ExecutionContext.SessionState` object. Requires the function be decorated with the `[CmdletBinding()]` attribute. # # Used to set variables in its callers' scope, even if that caller is in a different script module. $SessionState ) Set-StrictMode -Version 'Latest' # List of preference variables taken from the about_Preference_Variables and their common parameter name (taken from about_CommonParameters). $commonPreferences = @{ 'ErrorActionPreference' = 'ErrorAction'; 'DebugPreference' = 'Debug'; 'ConfirmPreference' = 'Confirm'; 'InformationPreference' = 'InformationAction'; 'VerbosePreference' = 'Verbose'; 'WarningPreference' = 'WarningAction'; 'WhatIfPreference' = 'WhatIf'; } foreach( $prefName in $commonPreferences.Keys ) { $parameterName = $commonPreferences[$prefName] # Don't do anything if the parameter was passed in. if( $Cmdlet.MyInvocation.BoundParameters.ContainsKey($parameterName) ) { continue } $variable = $Cmdlet.SessionState.PSVariable.Get($prefName) # Don't do anything if caller didn't use a common parameter. if( -not $variable ) { continue } if( $SessionState -eq $ExecutionContext.SessionState ) { Set-Variable -Scope 1 -Name $variable.Name -Value $variable.Value -Force -Confirm:$false -WhatIf:$false } else { $SessionState.PSVariable.Set($variable.Name, $variable.Value) } } } |