StatuspagePS.psm1
|
function Invoke-StatuspageRestMethod { [CmdletBinding()] param ( [parameter(Mandatory)] [string] $page, [hashtable] $body = $null, [ValidateSet('Get', 'Post', 'Patch', 'Delete')] [string] $method = 'Get', [int] $retryCount = 15, [int] $retrySecDelay = 15, [int] $perPage = $null ) if ($script:statuspageUrl -eq $null) { throw 'Unknown Statuspage url (run Set-StatuspageUrl)' } if ($script:statuspageHeaders -eq $null) { throw 'Unknown Statuspage headers (run Set-StatuspageHeaders)' } [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::TLS12 $retryAttempt = 0 if ($body) { $jsonBody = $body | ConvertTo-Json -Depth 10 } else { $jsonBody = $null } $uri = "$script:statuspageUrl/$page" $queryParameters = "" if ($perPage) { [int]$pageCounter = 1 $queryParameters = "?page=$pageCounter&per_page=$perPage" } $results = @() do { try { $url = $uri + $queryParameters $result = (Invoke-RestMethod -Uri $url -Headers $script:statuspageHeaders -Body $jsonBody -Method $method -ErrorAction Stop -Verbose) $results += $result if ($perPage -and ($result.count -eq $perPage)) { $done = $false $pageCounter = $pageCounter + 1 $queryParameters = "?page=$pageCounter&per_page=$perPage" Write-Verbose "Next page: $pageCounter" } else { $done = $true } } catch { Write-Warning "$($MyInvocation.MyCommand): retryAttempt=$retryAttempt/$retryCount uri=$url method=$method body=$jsonBody" Write-Warning $_ if ($retryAttempt -lt $retryCount) { Start-Sleep -Seconds $retrySecDelay $retryAttempt++ } else { throw $_ } } } while (-not $done) $results } function Get-StatuspageComponentGroupLookup { [CmdletBinding()] param ( [int] $retryCount = 15, [int] $retrySecDelay = 15, [int] $perPage = 50 ) $groupLookup = @{} $rawComponents = Invoke-StatuspageRestMethod -page components -Method Get -retryCount $retryCount -retrySecDelay $retrySecDelay -perPage $perPage foreach ($thisComponent in $rawComponents) { $isGroup = ($thisComponent.group -is [bool] -and $thisComponent.group) -or ($thisComponent.group -is [string] -and $thisComponent.group.Equals('true', [System.StringComparison]::OrdinalIgnoreCase)) if ($isGroup) { $groupLookup[[string]$thisComponent.id] = $thisComponent.name } } $groupLookup } function Convert-StatuspageComponent { [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [object] $object, [hashtable] $groupLookup = $null, [switch] $skipGroupNameLookup, [int] $retryCount = 15, [int] $retrySecDelay = 15, [int] $perPage = 50 ) begin { if ($skipGroupNameLookup) { $groupLookup = $null } elseif (-not $groupLookup) { $groupLookup = Get-StatuspageComponentGroupLookup -retryCount $retryCount -retrySecDelay $retrySecDelay -perPage $perPage } $components = @() } process { $groupId = [string]$object.group_id if ($groupLookup -and -not [string]::IsNullOrEmpty($groupId)) { $groupName = $groupLookup[$groupId] } else { $groupName = $null } $components += [PSCustomObject] @{ PSTypeName = 'statuspageComponent' id = $object.id pageId = $object.page_id groupId = $object.group_id groupName = $groupName createdAt = $object.created_at updatedAt = $object.updated_at group = $object.group name = $object.name description = $object.description position = $object.position status = $object.status showcase = $object.showcase onlyShowIfDegraded = $object.only_show_if_degraded automationEmail = $object.automation_email } } end { $components } } function Convert-StatuspageIncident { [CmdletBinding()] param ( [Parameter(Mandatory, ValueFromPipeline)] [object] $object, [hashtable] $componentsGroupLookup = $null, [switch] $skipComponentGroupNameLookup, [int] $retryCount = 15, [int] $retrySecDelay = 15, [int] $perPage = 50 ) begin { $incidents = @() } process { $componentArgs = @{ retryCount = $retryCount retrySecDelay = $retrySecDelay perPage = $perPage } if ($skipComponentGroupNameLookup) { $componentArgs.skipGroupNameLookup = $true } elseif ($componentsGroupLookup) { $componentArgs.groupLookup = $componentsGroupLookup } $incidents += [PSCustomObject] @{ PSTypeName = 'statuspageIncident' id = $object.id name = $object.name status = $object.status createdAt = $object.created_at updatedAt = $object.updated_at monitoringAt = $object.monitoring_at resolvedAt = $object.resolved_at impact = $object.impact shortlink = $object.shortlink scheduledFor = $object.scheduled_for scheduledUntil = $object.scheduled_until scheduledRemindPrior = $object.scheduled_remind_prior scheduledRemindedAt = $object.scheduled_reminded_at impactOverride = $object.impact_override scheduledAutoInProgress = $object.scheduled_auto_in_progress scheduledAutoCompleted = $object.scheduled_auto_completed metadata = $object.metadata startedAt = $object.started_at pageId = $object.page_id incidentUpdates = $object.incident_updates postmortemBody = $object.postmortem_body postmortemBodyLastUpdatedAt = $object.postmortem_body_last_updated_at postmortemIgnored = $object.postmortem_ignored postmortemPublishedAt = $object.postmortem_published_at postmortemNotifiedSubscribers = $object.postmortem_notified_subscribers postmortemNotifiedTwitter = $object.postmortem_notified_twitter components = ($object.components | Convert-StatuspageComponent @componentArgs) } } end { $incidents } } function Set-StatuspageUrl { [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $pageId ) $script:statuspageUrl = "https://api.statuspage.io/v1/pages/$pageId" } function Set-StatuspageHeaders { [CmdletBinding()] param ( [Parameter(Mandatory)] [string] $apiKey ) $script:statuspageHeaders = @{ 'Authorization' = "OAuth $apiKey" 'Content-Type' = 'application/json' } } function Get-StatuspageComponent { [CmdletBinding(DefaultParameterSetName = 'NoneParameterSetName')] param ( [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByName')] [string] $name, [Parameter(Mandatory, ParameterSetName = 'ById')] [string] $id, [int] $retryCount = 15, [int] $retrySecDelay = 15, [int] $perPage = 50 ) begin { $groupLookup = Get-StatuspageComponentGroupLookup -retryCount $retryCount -retrySecDelay $retrySecDelay -perPage $perPage $components = Invoke-StatuspageRestMethod -page components -Method Get -perPage $perPage -retryCount $retryCount -retrySecDelay $retrySecDelay | Convert-StatuspageComponent -groupLookup $groupLookup } process { if ($name) { $component = $components | Where-Object { $_.name -eq $name } if ($component) { $component } else { throw "Cannot find component with name $name" } } elseif ($id) { $component = $components | Where-Object { $_.id -eq $id } if ($component) { $component } else { throw "Cannot find component with id $id" } } else { $components } } } function New-StatuspageComponent { [CmdletBinding()] param ( [parameter(Mandatory, ValueFromPipeline)] [string] $name, [int] $retryCount = 15, [int] $retrySecDelay = 15 ) process { $body = @{ component = @{ name = $name } } Invoke-StatuspageRestMethod -page components -Method Post -retryCount $retryCount -retrySecDelay $retrySecDelay -Body $body | Convert-StatuspageComponent -retryCount $retryCount -retrySecDelay $retrySecDelay } } function New-StatuspageComponentGroup { [CmdletBinding()] param ( [parameter(Mandatory, ParameterSetName = 'ByObject')] [parameter(Mandatory, ParameterSetName = 'ById')] [string] $name, [parameter(Mandatory, ParameterSetName = 'ByObject')] [PSTypeName('statuspageComponent')] $component, [parameter(Mandatory, ParameterSetName = 'ById')] [string[]] $componentId, [int] $retryCount = 15, [int] $retrySecDelay = 15 ) if ($PsCmdlet.ParameterSetName -eq 'ByObject') { $thisComponentId = $component.id } elseif ($PsCmdlet.ParameterSetName -eq 'ById') { $thisComponentId = $componentId } $body = @{ component_group = @{ name = $name components = $thisComponentId } } Invoke-StatuspageRestMethod -page component-groups -Method Post -retryCount $retryCount -retrySecDelay $retrySecDelay -Body $body | Convert-StatuspageComponent -retryCount $retryCount -retrySecDelay $retrySecDelay } function Update-StatuspageComponent { [CmdletBinding()] param ( [parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByObject')] [PSTypeName('statuspageComponent')] $component, [parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ById')] [string[]] $componentId, [parameter(Mandatory, ParameterSetName = 'ByObject')] [parameter(Mandatory, ParameterSetName = 'ById')] [ValidateSet('operational', 'major_outage', 'degraded_performance', 'partial_outage', 'under_maintenance')] [string] $status, [int] $retryCount = 15, [int] $retrySecDelay = 15 ) begin { $body = @{ component = @{ status = $status } } } process { if ($PsCmdlet.ParameterSetName -eq 'ByObject') { $thisComponentId = $component.id } elseif ($PsCmdlet.ParameterSetName -eq 'ById') { $thisComponentId = $componentId } Invoke-StatuspageRestMethod -page "components/$thisComponentId" -method Patch -retryCount $retryCount -retrySecDelay $retrySecDelay -body $body | Convert-StatuspageComponent -retryCount $retryCount -retrySecDelay $retrySecDelay } } function Remove-StatuspageComponent { [CmdletBinding()] param ( [parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByObject')] [PSTypeName('statuspageComponent')] $component, [parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ById')] [string] $componentId, [int] $retryCount = 15, [int] $retrySecDelay = 15 ) process { if ($PsCmdlet.ParameterSetName -eq 'ByObject') { $thisComponent = $component } elseif ($PsCmdlet.ParameterSetName -eq 'ById') { $thisComponent = Get-StatuspageComponent -id $componentId } if ($thisComponent.group -eq $false) { Invoke-StatuspageRestMethod -page "components/$($thisComponent.id)" -Method Delete -retryCount $retryCount -retrySecDelay $retrySecDelay } } } function Get-StatuspageIncident { [CmdletBinding(DefaultParameterSetName = 'NoneParameterSetName')] param ( [parameter(ValueFromPipeline, ParameterSetName = 'ByComponent')] [PSTypeName('statuspageComponent')] $component, [parameter(ParameterSetName = 'ByQuery')] [string] $query, [parameter(ParameterSetName = 'ByComponent')] [parameter(ParameterSetName = 'ByQuery')] [string] $status, [parameter(ParameterSetName = 'ByComponent')] [switch] $queryComponentName, [switch] $unresolved, [switch] $scheduled, [switch] $active, [switch] $noComponentGroupNames, [int] $retryCount = 15, [int] $retrySecDelay = 15, [int] $limit = 100, [int] $perPage = 50 ) begin { $incidentConverterArgs = @{} if ($noComponentGroupNames) { $incidentConverterArgs.skipComponentGroupNameLookup = $true } else { $incidentConverterArgs.componentsGroupLookup = Get-StatuspageComponentGroupLookup -retryCount $retryCount -retrySecDelay $retrySecDelay -perPage $perPage } } process { $uri = 'incidents' if ($unresolved) { $uri += "/unresolved" } elseif ($scheduled) { $uri += "/scheduled" } elseif ($active) { $uri += "/active_maintenance" } if ($queryComponentName) { $uri += "?q=$($component.name)" } elseif ($query) { $uri += "?q=$query" } if ($limit -and -not $unresolved -and -not $scheduled -and -not $active) { $uri += "&limit=$limit" } if ($unresolved -or $scheduled -or $active) { $incidents = Invoke-StatuspageRestMethod -page $uri -Method Get -retryCount $retryCount -retrySecDelay $retrySecDelay -perPage $perPage | Convert-StatuspageIncident @incidentConverterArgs } else { $incidents = Invoke-StatuspageRestMethod -page $uri -Method Get -retryCount $retryCount -retrySecDelay $retrySecDelay | Convert-StatuspageIncident @incidentConverterArgs } if ($component) { $incidents = $incidents | Where-Object { $_.components.id -eq $component.id } } if ($status) { $incidents = $incidents | Where-Object { $_.status -eq $status } } $incidents } } function New-StatuspageIncident { [CmdletBinding()] param ( [parameter(Mandatory, ParameterSetName = 'ByObject')] [parameter(Mandatory, ParameterSetName = 'ById')] [string] $name, [parameter(Mandatory, ParameterSetName = 'ByObject')] [parameter(Mandatory, ParameterSetName = 'ById')] [string] $body, [parameter(Mandatory, ParameterSetName = 'ByObject')] [parameter(Mandatory, ParameterSetName = 'ById')] [ValidateSet('investigating', 'identified', 'monitoring', 'resolved', 'scheduled', 'in_progress', 'verifying', 'completed', 'update')] [string] $status, [parameter(Mandatory, ParameterSetName = 'ByObject')] [PSTypeName('statuspageComponent')] $component, [parameter(Mandatory, ParameterSetName = 'ById')] [string[]] $componentId, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [ValidateSet('operational', 'major_outage', 'degraded_performance', 'partial_outage', 'under_maintenance')] [string] $componentStatus, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [hashtable] $metadata, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [dateTime] $scheduledFor, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [dateTime] $scheduledUntil, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [switch] $deliverNotifications, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [switch] $scheduledRemindPrior, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [switch] $scheduledAutoCompleted, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [switch] $scheduledAutoInProgress, [int] $retryCount = 15, [int] $retrySecDelay = 15 ) if ($PsCmdlet.ParameterSetName -eq 'ByObject') { $thisComponentId = $component.id } elseif ($PsCmdlet.ParameterSetName -eq 'ById') { $thisComponentId = $componentId } $thisIncident = @{ name = $name body = $body status = $status component_ids = $thisComponentId } if ($componentStatus) { $thisIncident.components = $thisComponentId | ForEach-Object { @{ $_ = $componentStatus } } } if ($metadata) { $thisIncident.metadata = $metadata } if ($status -in 'in_progress', 'scheduled') { if ($scheduledFor -eq $null -or $scheduledUntil -eq $null) { throw "status=$status require parameters `$scheduledFor and `$scheduledUntil" } else { $thisIncident.scheduled_for = $scheduledFor | Get-Date -Format "yyyy-MM-dd'T'HH:mm:00.000'Z'" $thisIncident.scheduled_until = $scheduledUntil | Get-Date -Format "yyyy-MM-dd'T'HH:mm:00.000'Z'" } } $thisIncident.scheduled_remind_prior = $scheduledRemindPrior.IsPresent $thisIncident.scheduled_auto_completed = $scheduledAutoCompleted.IsPresent $thisIncident.scheduled_auto_in_progress = $scheduledAutoInProgress.IsPresent $thisIncident.deliver_notifications = $deliverNotifications.IsPresent Invoke-StatuspageRestMethod -page incidents -method Post -retryCount $retryCount -retrySecDelay $retrySecDelay -body @{ incident = $thisIncident } | Convert-StatuspageIncident -retryCount $retryCount -retrySecDelay $retrySecDelay } function Update-StatuspageIncident { [CmdletBinding()] param ( [parameter(Mandatory, ParameterSetName = 'ByObject')] [PSTypeName('statuspageIncident')] $incident, [parameter(Mandatory, ParameterSetName = 'ById')] [string] $incidentId, [parameter(Mandatory, ParameterSetName = 'ByObject')] [parameter(Mandatory, ParameterSetName = 'ById')] [string] $body, [parameter(Mandatory, ParameterSetName = 'ByObject')] [parameter(Mandatory, ParameterSetName = 'ById')] [ValidateSet('investigating', 'identified', 'monitoring', 'resolved', 'scheduled', 'in_progress', 'verifying', 'completed', 'update')] [string] $status, [parameter(Mandatory, ParameterSetName = 'ByObject')] [PSTypeName('statuspageComponent')] $component, [parameter(Mandatory, ParameterSetName = 'ById')] [string[]] $componentId, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [ValidateSet('operational', 'major_outage', 'degraded_performance', 'partial_outage', 'under_maintenance')] [string] $componentStatus, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [hashtable] $metadata, [parameter(ParameterSetName = 'ByObject')] [parameter(ParameterSetName = 'ById')] [switch] $deliverNotifications, [int] $retryCount = 15, [int] $retrySecDelay = 15 ) if ($PsCmdlet.ParameterSetName -eq 'ByObject') { $thisComponentId = $component.id $thisIncidentId = $incident.id } elseif ($PsCmdlet.ParameterSetName -eq 'ById') { $thisComponentId = $componentId $thisIncidentId = $incidentId } $thisIncident = @{ body = $body status = $status component_ids = $thisComponentId } if ($componentStatus) { $thisIncident.components = $thisComponentId | ForEach-Object { @{ $_ = $componentStatus } } } if ($metadata) { $thisIncident.metadata = $metadata } $thisIncident.deliver_notifications = $deliverNotifications.IsPresent Invoke-StatuspageRestMethod -page "incidents/$thisIncidentId" -method Patch -retryCount $retryCount -retrySecDelay $retrySecDelay -body @{ incident = $thisIncident } | Convert-StatuspageIncident -retryCount $retryCount -retrySecDelay $retrySecDelay } function Remove-StatuspageIncident { [CmdletBinding()] param ( [parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByObject')] [PSTypeName('statuspageIncident')] $incident, [parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ById')] [string] $incidentId, [int] $retryCount = 15, [int] $retrySecDelay = 15 ) process { if ($PsCmdlet.ParameterSetName -eq 'ByObject') { $thisIncidentId = $incident.id } elseif ($PsCmdlet.ParameterSetName -eq 'ById') { $thisIncidentId = $incidentId } Invoke-StatuspageRestMethod -page "incidents/$thisIncidentId" -Method Delete -retryCount $retryCount -retrySecDelay $retrySecDelay | Convert-StatuspageIncident -retryCount $retryCount -retrySecDelay $retrySecDelay } } |