NewRelicPS.Configuration.Channel.psm1
<#
.Synopsis Idempotently applies New Relic channel configurations .Description Idempotently applies New Relic channel configurations .Example Set-NRChannelConfiguration -APIKey $AdminAPIKey -DefinedChannels $MyChannels -OpsGenieAPIKey $OpsGenieAPIKey Uses New Relic APIs to update notification channels to match the channels defined in $MyChannels. Any existing channels that are not defined will be removed. .Parameter APIKey Must be an admin user's API Key, not an account-level REST API Key. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys .Parameter DefinedChannels An array of channel objects which define the desired configuration state for New Relic notification channels .Parameter OpsGenieAPIKey The APIKey New Relic uses to send OpsGenie alerts #> Function Set-NRChannelConfiguration { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", '', Justification = "All CMDLets being called have ShouldProcess in place and the preference is passed to them." )] [CMDLetBinding(SupportsShouldProcess=$true)] Param ( [Parameter (Mandatory = $true)] [string] $APIKey, [Parameter (Mandatory = $false)] [array] $DefinedChannels ) # Get existing notificaiton channels but exclude the built-in user channels which can't be edited [System.Collections.ArrayList]$existingChannels = Get-NRNotificationChannel -APIKey $APIKey | Where-Object { $_.type -ne 'user' } Write-Verbose "There are currently $($DefinedChannels.count) defined channels and $($existingChannels.count) existing channels." Foreach ($channel in $DefinedChannels) { $CurrentConfig = $existingChannels | Where-Object { $_.name -eq $channel.name } # Update the channel if required If ($CurrentConfig) { $configurationDiff = Compare-ChannelConfiguration -CurrentConfig $CurrentConfig.configuration -DefinedConfig $channel.configuration # The API Key is not returned on the channel and cannot be checked If ($configurationDiff -or $channel.type -ne $CurrentConfig.type) { # There is no update endpoint for channels, so it must be recreated Write-Verbose "Recreating channel $($channel.name)" Remove-NRNotificationChannel -APIKey $APIKey -ChannelID $CurrentConfig.id -WhatIf:$WhatIfPreference New-NRNotificationChannel -APIKey $APIKey -Name $channel.name -Type $channel.type -Configuration $channel.configuration -WhatIf:$WhatIfPreference | Out-Null } # Any extra existing channels that are not defined will be removed later $existingChannels.Remove($CurrentConfig) } # Create the channel if it doesn't exist Else { Write-Verbose "Creating channel $($channel.name)" New-NRNotificationChannel -APIKey $APIKey -Name $channel.name -Type $channel.type -Configuration $channel.configuration -WhatIf:$WhatIfPreference | Out-Null } } # Check for existing channels not in the definition and remove them If ($existingChannels) { Write-Verbose "Removing channel(s) $($existingChannels.name -join(','))" $existingChannels.Id | Remove-NRNotificationChannel -APIKey $APIKey -WhatIf:$WhatIfPreference | Out-Null } } <# .Synopsis Idempotently applies New Relic channel-policy link configurations .Description Idempotently applies New Relic channel-policy link configurations .Example Set-NRChannelPolicyLink -APIKey $AdminAPIKey -DefinedPolicies $Config.AlertPolicies Uses New Relic APIs to update policy-channel links to match the channels defined in $Config.AlertPolicies. Any existing links that are not defined will be removed. .Parameter APIKey Must be an admin user's API Key, not an account-level REST API Key. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys .Parameter DefinedPolicies An array of policy objects which define the desired configuration state for New Relic alert policies #> Function Set-NRChannelPolicyLink { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", '', Justification = "All CMDLets being called have ShouldProcess in place and the preference is passed to them." )] [CMDLetBinding(SupportsShouldProcess = $true)] Param ( [Parameter (Mandatory = $true)] [string] $APIKey, [Parameter (Mandatory = $false)] [array] $DefinedPolicies ) $existingPolicies = Get-NRAlertPolicy -APIKey $APIKey $existingChannels = Get-NRNotificationChannel -APIKey $APIKey # Notification channels are described in a policy, but the API only returns the link in the notification channel Foreach ($policy in $DefinedPolicies) { $CurrentPolicyConfig = $existingPolicies | Where-Object { $_.name -eq $policy.name } # Iterate over each channel in the policy described in the policy Foreach ($channelName in $policy.channels) { $CurrentChannelConfig = $existingChannels | Where-Object { $_.name -eq $channelName } # If the current channel configuration's link does not contain the ID of the policy, add a new link If ($CurrentChannelConfig -and $CurrentChannelConfig.links.policy_ids -notcontains $CurrentPolicyConfig.id) { # This command doesn't remove any existing links, it only appends the new link Write-Verbose "Adding policy-channel link for policy $($policy.name) and channel $channelName" Add-NRNotificationChannelToAlertPolicy -APIKey $APIKey -PolicyId $CurrentPolicyConfig.id -ChannelIds $CurrentChannelConfig.id -WhatIf:$WhatIfPreference | Out-Null } } } # Remove extra links Write-Verbose 'Checking for extra channel/policy links.' Foreach ($channel in $existingChannels) { # A channel can be linked to multiple policies so check each Foreach ($policyId in $channel.links.policy_ids) { $policyName = ($existingPolicies | Where-Object { $_.id -eq $policyId }).name $definedPolicy = $DefinedPolicies | Where-Object { $_.name -eq $policyName } # If the policy declaration doesn't contain the channel name, delete the link. If ($definedPolicy.channels -notcontains $channel.name) { Write-Verbose "Removing policy-channel link for policy $policyName and channel $($channel.name)" Remove-NRNotificationChannelFromAlertPolicy -APIKey $APIKey -PolicyId $policyId -ChannelId $channel.id -WhatIf:$WhatIfPreference } } } } ############################ # Internal Functions ############################ Function Compare-ChannelConfiguration { Param ( [Parameter (Mandatory = $true)] $CurrentConfig, [Parameter (Mandatory = $true)] $DefinedConfig ) $result = $false $diff = $null # Some items are not returned from the channel API and cannot be compared $itemsToExclude = @('api_Key') Foreach ($item in $DefinedConfig.keys) { # Tags requires special processing If ($item -eq 'tags') { $diff = Compare-Object ($CurrentConfig.tags -split (' ')) ($DefinedConfig.tags -split (' ')) If ($diff) { Write-Verbose 'Difference found between defined and current channel configuration tags' $result = $true } } # Compare the rest of the non-excluded items ElseIf ($item -notin $itemsToExclude) { If ($DefinedConfig.$item -ne $CurrentConfig.$item) { Write-Verbose "Difference found between defined and current configuration $item" $result = $true } } } Return $result } |