NewRelicPS.SyntheticMonitors.psm1
<# .Synopsis Gets New Relic Synthetic Monitor Locations .Description Returns a list of valid synthetic monitor locations .Example Get-NRSyntheticLocationList -APIKey $APIKey Returns a list of synthetic monitor locations .Parameter APIKey This must be an Admin API key. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys #> Function Get-NRSyntheticLocationList { [CMDLetBinding()] Param ( [Parameter (Mandatory = $true)] [string] $APIKey ) $headers = @{ 'X-Api-Key' = $APIKey } $url = 'https://synthetics.newrelic.com/synthetics/api/v1/locations' # Call the API Invoke-RestMethod -Uri $url -Headers $headers -Method 'Get' -ContentType 'application/json' } <# .Synopsis Gets New Relic Synthetic Monitors .Description Gets all New Relic synthetic monitors in an account or returns a specific monitor if a monitor ID is provided. This command only works with synthetic condition types. .Example Get-NRSyntheticMonitor -APIKey $APIKey -AccountId 12345678 Gets information on all New Relic synthetic monitors in the account associated with the API key provided. .Example Get-NRSyntheticMonitor -APIKey $APIKey -Id 123 Returns only data for the monitor with id 123 in the account associated with the API key provided. Returns null if no existing monitor has the ID provided. .Parameter APIKey This must be an Admin API key. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys .Parameter Id Filters results to the single monitor with the Id specified. Returns null if a monitor with the specified Id is not found. #> Function Get-NRSyntheticMonitor { [CMDLetBinding()] Param ( [Parameter (Mandatory = $true)] [string] $APIKey, [Parameter (ValueFromPipelineByPropertyName = $true)] [string] $Id ) Begin { $headers = @{ 'X-Api-Key' = $APIKey } } Process { $url = 'https://synthetics.newrelic.com/synthetics/api/v3/monitors' If ($Id) { $url += "/$Id" } # Call the API and return null if a monitor ID is provided but not found try { $result = Invoke-RestMethod -Uri $url -Headers $headers -Method 'Get' -ContentType 'application/json' } catch { If ($_.Exception.Response.StatusCode.Value__ -ne '404') { Write-Error $_ } } # The result is wrapped in the monitors property unless a single result is returned so use turnary to return consistent results $result.monitors ? $result.monitors : $result } } <# .Synopsis Gets New Relic Synthetic Monitor Script .Description Gets the Base64 encoded script contents for a Synthetic Monitor. .Example Get-NRSyntheticMonitorScript -APIKey $APIKey -Id 12345678 Gets the script content for monitor Id 12345678 .Parameter APIKey This must be an Admin API key. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys .Parameter Id The Id for the Synthetic monitor to return the script content from. Must be of type SCRIPT_API or SCRIPT_BROWSER. #> Function Get-NRSyntheticMonitorScript { [CMDLetBinding()] Param ( [Parameter (Mandatory = $true)] [string] $APIKey, [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $Id ) Begin { $headers = @{ 'X-Api-Key' = $APIKey } } Process { $url = "https://synthetics.newrelic.com/synthetics/api/v3/monitors/$Id/script" # Call the API and return null if a monitor ID is provided but not found Invoke-RestMethod -Uri $url -Headers $headers -Method 'Get' -ContentType 'application/json' } } <# .Synopsis Creates a New Relic Synthetic Monitor .Description Creates a New Relic synthetic monitor. .Example New-NRSyntheticMonitor -APIKey $APIKey -Name 'MySyntheticMonitor' -Locations 'AWS_US_EAST_1,AWS_US_EAST_2' -URI 'https://some.net' Creates a new Synthetics monitor which pings 'https://some.net' every 10 minutes (by default) from two locations. .Example ScriptVariables = @{ENVIRONMENT_DOMAIN='some.net'} New-NRSyntheticMonitor -APIKey $APIKey -Type 'Script_API' -ScriptVariables $ScriptVariables -ScriptPath $scriptPath -Name 'MyScriptedSyntheticMonitor' -Locations 'AWS_US_EAST_1,AWS_US_EAST_2' -URI 'https://some.net' Creates a new scripted Synthetics monitor and templates in the provided domain name to the script at $scriptPath during runtime .Parameter APIKey This must be an Admin API key. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys .Parameter BypassHeadRequest Skips the default HEAD request and instead uses the GET verb with a ping check. Defaults to True. Valid only for SIMPLE monitors. .Parameter Frequency Determines how often the monitor pings the resource in minutes. Defaults to 10. Valid options are 1, 5, 10, 15, 30, 60, 360, 720, or 1440. .Parameter Locations An array of locations to probe from. Get available options by running the Get-NRSyntheticLocation CMDLet. .Parameter Name The friendly name used to identify the monitor. .Parameter ScriptVariables A hash table of scriptvariables to replace in a monitor's script. .Parameter ScriptPath File path for the script to be used for scripted monitors. Valid only for SCRIPT_API and SCRIPT_BROWSER. .Parameter SlaThreshold The number of seconds for a check to finish witin to be considered satisfying. Defaults to 7. Checks finishing between 1-4 times this value are considered tolerated and above 4x is considered frustrating. .Parameter Status The status of the newly created monitor. Defaults to ENABLED. Valid options are ENABLED, MUTED, DISABLED. .Parameter TreatRedirectAsFailure Whether any redirect will result in a failure. Defaults to False. Valid only for SIMPLE monitors. .Parameter Type Specifies which type of synthetic monitor to create. Defaults to 'SIMPLE'. Valid options are 'SIMPLE','BROWSER','SCRIPT_API','SCRIPT_BROWSER'. .Parameter URI The URI of the resource to ping. Required for SIMPLE and BROWSER monitor types. .Parameter ValidationString A string expected to be returned in valid responses. Valid only for SIMPLE and BROWSER monitors. .Parameter VerifySSL Specifies whether each check will run a detailed OpenSSL handshake and alert on failures. Defaults to false. Valid only for SIMPLE and BROWSER monitors. #> Function New-NRSyntheticMonitor { [CMDLetBinding(SupportsShouldProcess=$true)] Param ( [Parameter (Mandatory = $true)] [string] $APIKey, [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $Name, [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [array] $Locations, [Parameter (ValueFromPipelineByPropertyName = $true)] [boolean] $BypassHeadRequest = $true, [Parameter (ValueFromPipelineByPropertyName = $true)] [ValidateSet (1,5, 10, 15, 30, 60, 360, 720, 1440)] [Int32] $Frequency= 10, [Parameter (ValueFromPipelineByPropertyName = $true)] [object] $ScriptVariables = @{}, [Parameter (ValueFromPipelineByPropertyName = $true)] [string] $ScriptPath, [Parameter (ValueFromPipelineByPropertyName = $true)] [Double] $SlaThreshold = 7, [Parameter (ValueFromPipelineByPropertyName = $true)] [ValidateSet ('ENABLED', 'MUTED', 'DISABLED')] [string] $Status = 'ENABLED', [Parameter (ValueFromPipelineByPropertyName = $true)] [boolean] $TreatRedirectAsFailure, [Parameter (ValueFromPipelineByPropertyName = $true)] [ValidateSet ('SIMPLE','BROWSER','SCRIPT_API','SCRIPT_BROWSER')] [string] $Type = 'SIMPLE', [Parameter (ValueFromPipelineByPropertyName = $true)] [string] $URI, [Parameter (ValueFromPipelineByPropertyName = $true)] [string] $ValidationString, [Parameter (ValueFromPipelineByPropertyName = $true)] [boolean] $VerifySSL = $false ) Begin { $url = 'https://synthetics.newrelic.com/synthetics/api/v3/monitors' $headers = @{ 'X-Api-Key' = $APIKey } } Process { # Check for URI on Simple and Browser type creation requests If (($Type -eq 'SIMPLE' -or $Type -eq 'BROWSER') -and [string]::IsNullOrWhiteSpace($URI)){ Write-Error "A URI is required when creating a monitor of type $Type." } # Build up the body of the request $Body = @{ name = $Name type = $Type frequency = $Frequency locations = $Locations status = $Status slaThreshold = $SlaThreshold } # Simple and browser monitors have some unique parameters If ($Type -eq 'SIMPLE' -or $Type -eq 'BROWSER') { $monitorOptions = @{ verifySSL = $VerifySSL } If ($ValidationString) { $monitorOptions += @{ validationString = $ValidationString } } # Some parameters are only valid with SIMPLE monitors If ($Type -eq 'SIMPLE') { $monitorOptions += @{ bypassHEADRequest = $BypassHeadRequest treatRedirectAsFailure = $TreatRedirectAsFailure } } # Add parameters specific to simple and browser monitors $Body += @{ uri = $URI options = $monitorOptions } } # Call the API If ($PSCmdlet.ShouldProcess($Name, "Create synthetic monitor")) { Invoke-RestMethod -Uri $url -Headers $headers -Body ($Body | ConvertTo-Json) -Method 'Post' -ContentType 'application/json' } # The API requires the monitor to be created in one call and then updated with a script in a second call. If ($Type -eq 'SCRIPT_API' -or $Type -eq 'SCRIPT_BROWSER') { If ([string]::IsNullOrWhiteSpace($ScriptPath) -or -NOT (Test-Path $ScriptPath)) { Write-Error "A valid script path is required when creating a monitor of type $Type." } # Get templated and encoded script content $scriptContent = Get-NRScriptContent -ScriptPath $ScriptPath -ScriptVariables $ScriptVariables # Get the new monitor's Id because the API does not return it from the post call $monitor = Get-NRSyntheticMonitor -APIKey $APIKey | Where-Object {$_.name -eq $Name} # Throw an error if the monitor isn't found or if there are more than 1 monitor returned Switch ($monitor.name.count) { 0 {Write-Error "There was a problem setting the script on the monitor. The monitor with name $Name was not found" } {$_ -gt 1} {Write-Error "There was a problem setting the script on the monitor. More than one monitor was found with the name $Name"} } Update-NRSyntheticMonitorScript -APIKey $APIKey -Id $monitor.id -ScriptContent $scriptContent } } } <# .Synopsis Deletes a New Relic Synthetic Monitor .Description Deletes a New Relic synthetic monitor. .Example Remove-NRSyntheticMonitor -APIKey $APIKey -Id '123456' Deletes the synthetic monitor with ID 123456 from the account associated with the provided API key .Example $Ids | Remove-NRSyntheticMonitor -APIKey $APIKey Deletes all syntheic monitors whose Id are listed in $Ids from the account associated with the provided API key .Parameter APIKey This must be an Admin API key. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys .Parameter Id The unique Id of the monitor to remove. #> Function Remove-NRSyntheticMonitor { [CMDLetBinding(SupportsShouldProcess=$true)] Param ( [Parameter (Mandatory = $true)] [string] $APIKey, [Parameter (Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string] $Id ) Begin { $headers = @{ 'X-Api-Key' = $APIKey } } Process { $url = "https://synthetics.newrelic.com/synthetics/api/v3/monitors/$Id" # Call the API If ($PSCmdlet.ShouldProcess($Id, "Remove synthetic monitor")) { Invoke-RestMethod -Uri $url -Headers $headers -Method 'Delete' -ContentType 'application/json' } } } <# .Synopsis Updates a New Relic Synthetic Monitor .Description Updates a New Relic synthetic monitor. .Example Update-NRSyntheticMonitor -APIKey $APIKey -Id '123456' -Frequency 5 Updates the monitor with ID 123456 so that it is checked every 5 minutes. .Example $Ids | Update-NRSyntheticMonitor -APIKey $APIKey -Id '123456' -SlaThreshold 4.25 Updates all monitors in the $Ids array with an SlaThreshold of 4.25 and leaves all other existing properties untouched. .Example ScriptVariables = @{ENVIRONMENT_DOMAIN='some.net'} Update-NRSyntheticMonitor -APIKey $APIKey -Id '123456' -Type 'Script_API' -ScriptVariables $ScriptVariables -ScriptPath $scriptPath Updates a scripted Synthetics monitor and templates in the provided domain name to the script at $scriptPath during runtime .Parameter APIKey This must be an Admin API key. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys .Parameter BypassHeadRequest Skips the default HEAD request and instaed uses the GET verb with a ping check. Defaults to True. Valid only for SIMPLE monitors. .Parameter Frequency Determines how often the monitor pings the resource in minutes. Defaults to 10. Valid options are 1, 5, 10, 15, 30, 60, 360, 720, or 1440. .Parameter Id The Id of the monitor to update. .Parameter Locations An array of locations to probe from. Get available options by running the Get-NRSyntheticLocation CMDLet. .Parameter Name The friendly name used to identify the monitor. .Parameter ScriptVariables A hash table of scriptvariables to replace in a monitor's script. .Parameter ScriptPath File path for the script to be used for scripted monitors. Valid only for SCRIPT_API and SCRIPT_BROWSER. .Parameter SlaThreshold The number of seconds for a check to finish witin to be considered satisfying. Defaults to 7. Checks finishing between 1-4 times this value are considered tolerated and above 4x is considered frustrating. .Parameter Status The status of the newly created monitor. Defaults to ENABLED. Valid options are ENABLED, MUTED, DISABLED. .Parameter TreatRedirectAsFailure Whether any redirect will result in a failure. Defaults to False. Valid only for SIMPLE monitors. .Parameter URI The URI of the resource to ping. Required for SIMPLE and BROWSER monitor types. .Parameter ValidationString A string expected to be returned in valid responses. Valid only for SIMPLE and BROWSER monitors. .Parameter VerifySSL Specifies whether each check will run a detailed OpenSSL handshake and alert on failures. Defaults to false. Valid only for SIMPLE and BROWSER monitors. #> Function Update-NRSyntheticMonitor { [CMDLetBinding(SupportsShouldProcess=$true)] Param ( [Parameter (Mandatory = $true)] [string] $APIKey, [Parameter (Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string] $Id, [Parameter (ValueFromPipelineByPropertyName = $true)] [Nullable[boolean]] $BypassHeadRequest, [Parameter (ValueFromPipelineByPropertyName = $true)] [ValidateSet (1,5, 10, 15, 30, 60, 360, 720, 1440)] [Int32] $Frequency, [Parameter (ValueFromPipelineByPropertyName = $true)] [array] $Locations, [Parameter (ValueFromPipelineByPropertyName = $true)] [string] $Name, [Parameter (ValueFromPipelineByPropertyName = $true)] [object] $ScriptVariables = @{}, [Parameter (ValueFromPipelineByPropertyName = $true)] [string] $ScriptPath, [Parameter (ValueFromPipelineByPropertyName = $true)] [Double] $SlaThreshold, [Parameter (ValueFromPipelineByPropertyName = $true)] [ValidateSet ('ENABLED', 'MUTED', 'DISABLED')] [string] $Status, [Parameter (ValueFromPipelineByPropertyName = $true)] [Nullable[boolean]] $TreatRedirectAsFailure, [Parameter (ValueFromPipelineByPropertyName = $true)] [string] $URI, [Parameter (ValueFromPipelineByPropertyName = $true)] [string] $ValidationString, [Parameter (ValueFromPipelineByPropertyName = $true)] [Nullable[boolean]] $VerifySSL ) Begin { $headers = @{ 'X-Api-Key' = $APIKey } } Process { $url = "https://synthetics.newrelic.com/synthetics/api/v3/monitors/$Id" # Build up the list of top-level fields to update $FieldsToUpdate = @{} Switch ($true) { { -NOT [string]::IsNullOrWhiteSpace($Name) } { $FieldsToUpdate += @{ name =$Name }} { $Frequency } { $FieldsToUpdate += @{ frequency = $Frequency }} { -NOT [string]::IsNullOrWhiteSpace($URI) } { $FieldsToUpdate += @{ uri = $URI }} { $Locations } { $FieldsToUpdate += @{ locations = $Locations }} { $Status } { $FieldsToUpdate += @{ status = $Status }} { $SlaThreshold } { $FieldsToUpdate += @{ slaThreshold = $SlaThreshold }} } # The options object is not idempotent by default so updating a value could remove other values by default If ("$ValidationString" -or "$VerifySSL" -or "$BypassHeadRequest" -or "$TreatRedirectAsFailure") { # Get the existing options $ExistingOptions = (Get-NRSyntheticMonitor -APIKey $APIKey -Id $Id).options # Use turnary operator to merge existing options with user provided options. If neither an existing or user provided option exists it is sent as null. $FieldsToUpdate['options'] += @{ validationString = $ValidationString ? $ValidationString : $ExistingOptions.validationString verifySSL = "$VerifySSL" ? $($VerifySSL.tostring().tolower()) : $ExistingOptions.verifySSL bypassHEADRequest = "$BypassHeadRequest" ? $($BypassHeadRequest.tostring().tolower()) : $ExistingOptions.bypassHEADRequest treatRedirectAsFailure = "$treatRedirectAsFailure" ? $($TreatRedirectAsFailure.tostring().tolower()) : $ExistingOptions.treatRedirectAsFailure } } # Only update the monitor if there is something to update If ($FieldsToUpdate.keys.count -gt 0) { # Call the API If ($PSCmdlet.ShouldProcess($Id, "Update synthetic monitor")) { Invoke-RestMethod -Uri $url -Headers $headers -Body ($FieldsToUpdate | ConvertTo-Json) -Method 'Patch' -ContentType 'application/json' } } # Update the monitor script if provided If (-NOT [string]::IsNullOrWhiteSpace($ScriptPath)) { # Get templated and encoded script content $scriptContent = Get-NRScriptContent -ScriptPath $ScriptPath -ScriptVariables $ScriptVariables # Call the update CMDLet If ($PSCmdlet.ShouldProcess($Id, "Update synthetic monitor script")) { Update-NRSyntheticMonitorScript -APIKey $APIKey -Id $Id -ScriptContent $scriptContent } } } } <# .Synopsis Updates a New Relic Synthetic Monitor Script .Description Updates a New Relic synthetic monitor script .Example Update-NRSyntheticMonitorScript -APIKey $APIKey -Id '123456' -ScriptContent $Base64EncodedScript Updates the monitor with ID 123456 with the script content provided .Parameter APIKey This must be an Admin API key. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys .Parameter Id The unique Id for the Synthetic monitor to udpate with script content. Must be a SCRIPT_API or SCRIPT_BROWSER type. .Parameter ScriptContent The Base64 encoded script to be run for the monitor. #> Function Update-NRSyntheticMonitorScript { [CMDLetBinding(SupportsShouldProcess=$true)] Param ( [Parameter (Mandatory = $true)] [string] $APIKey, [Parameter (Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string] $Id, [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [string] $ScriptContent ) Begin { $url = "https://synthetics.newrelic.com/synthetics/api/v3/monitors/$Id/script" $headers = @{ 'X-Api-Key' = $APIKey } } Process { # Build up the body of the request $body = @{ scriptText = $ScriptContent } | ConvertTo-Json # Call the API If ($PSCmdlet.ShouldProcess($Name, "Create synthetic monitor")) { Invoke-RestMethod -Uri $url -Headers $headers -Body $body -Method 'Put' -ContentType 'application/json' } } } ############################## # Internal Functions ############################## Function Get-NRScriptContent { Param( [Parameter (Mandatory = $true)] [string] $ScriptPath, [object] $ScriptVariables ) If (Test-Path $ScriptPath) { $scriptContent = Get-Content $ScriptPath -Raw Foreach ($key in $ScriptVariables.keys) { $scriptContent = $scriptContent.replace("`${$key}", $ScriptVariables.$key) } Return [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($scriptContent)) } Else { Throw [System.IO.FileNotFoundException]::new("Unable to get Synthetics script content. File not found at path $scriptPath.") } } |