NewRelicPS.Dashboards.psm1

Using module .\NewRelicPS.GraphQLQueries.psm1

<#
.Synopsis
  Copies a New Relic dashboard
.Description
  Copies the specified New Relic dashboard to another account.
  A new dashboard is created in the destination account if one doesn't already exist with a name matching the source dashboard.
  If a dashboard exists in the destination account with the same name as the source, that dashboard will be updated with the configuration from the source dashboard.
 
.Example
  $Id = (Get-NRDashboardList -APIKey $apikey -NameFilter 'MyDashboard').guid
  Copy-NRDashboard -APIKey $APIKey -AccountId '12345678' -DashboardId $Id -UpdateWidgetAccountIds
  Copies the New Relic dashboard 'Mydashboard' to the account with Id 12345678 and updates all widgets to the new account's Id.
.Parameter APIKey
  This must be a 'Personal API Key'. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys.
.Parameter DashboardId
  GUID for the dashboard to copy. This can be retrieved by using the Get-NRDashboardList CMDLet.
.Parameter DestinationAccountId
  The New Relic assigned Id for the New Relic account containing conditions.
.Parameter UpdateWidgetAccountIds
  Replaces all widget account Ids on the dashboard being copied with the destination account Id. Useful when copying a dashboard between accounts representing environments.
#>

Function Copy-NRDashboard {
  [CMDLetBinding(SupportsShouldProcess)]
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter (Mandatory = $true)]
    [string] $DashboardId,
    [Parameter (Mandatory = $true)]
    [string] $DestinationAccountId,
    [Parameter ()]
    [switch] $UpdateWidgetAccountIds
  )
  Process {
    $dashboardConfig = Get-NRDashboard -APIKey $APIKey -DashboardID $DashboardId

    # If specified, swap out the account ids on all widgets to the destination account
    If ($UpdateWidgetAccountIds) {
      $dashboardConfig = Update-NRDashboardWidgetAccountID -AccountId $DestinationAccountId -DashboardConfig $dashboardConfig
    }

    # Find Dashboard in Destination
    $destinationDashboardGuid = (Get-NRDashboardList -APIKey $APIKey | Where-Object { $_.name -eq $dashboardConfig.name -and $_.accountId -eq $DestinationAccountId }).guid

    If ($PSCmdlet.ShouldProcess('Copy Dashboard')) {

      # Create dashboard if missing
      If ($destinationDashboardGuid.count -lt 1) {
        Write-Verbose "No matching dashboard with name $($dashboardConfig.name) found in destination account with id $DestinationAccountId. Creating new Dashboard..."
        $destinationDashboardGuid = (New-NRDashboard -APIKey $APIKey -DashboardConfig $dashboardConfig -AccountId $DestinationAccountId).entityresult.guid
      }
      ElseIf ($destinationDashboardGuid.count -gt 1) {
        Throw "More than one dashboard was found with the same name: $($dashboardConfig.name)! This CMDLet doesn't support multiple dashboards with the same name in the same New Relic account."
      }

      # Update Dashboard
      Update-NRDashboard -APIKey $APIKey -DashboardConfig $dashboardConfig -DashboardId $destinationDashboardGuid
    }
  }
}

<#
.Synopsis
  Get a New Relic dashboard
.Description
  Returns the dashboard configuration, for the dashboard Id specified.
.Example
  $Id = (Get-NRDashboardList -APIKey $apikey -NameFilter 'MyDashboard').guid
  Get-NRDashboard -APIKey $APIKey -Dashboard $Id
  Returns dashboard configuration for the dashboard with name 'MyDashboard', including pages and configuration. Note that this example assumes there is only one dashboard containing the name 'MyDashboard'.
.Parameter APIKey
  This must be a 'Personal API Key'. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys.
.Parameter DashboardId
  GUID for the dashboard to copy. This can be retrieved by using the Get-NRDashboardList CMDLet.
#>

Function Get-NRDashboard {
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter (Mandatory = $true)]
    [string] $DashboardId
  )

  Begin {
    $URL = 'https://api.newrelic.com/graphql'

    # Create header for authorization
    $headers = @{
      'Api-Key' = $APIKey
    }
  }
  Process {
    $graphqlQuery = Get-GraphQLQueryGetDashboard -DashboardId $DashboardId

    # Build the body of the API call using the query
    $body = @{
      query = $graphqlQuery
    } | ConvertTo-Json

    # Call API
    Return (Invoke-RestMethod -Uri $URL -Method 'Post' -Headers $Headers -Body $body -ContentType 'application/json').data.actor.entity
  }
}

<#
.Synopsis
  Get a list of New Relic dashboards
.Description
  Returns a list of New Relic dashboards the provided APIKey has access to across New Relic accounts.
.Example
  Get-NRDashboardList -APIKey $apikey
  Returns a list of all dashboards the provided API key has access to across New Relic accounts.
.Example
  Get-NRDashboardList -APIKey $apikey -NameFilter 'MyDashboard'
  Returns a list of all dashboards containing the name 'MyDashboard' across New Relic accounts.
.Parameter APIKey
  This must be a 'Personal API Key'. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys.
.Parameter NameFilter
  If provided, the list of dashboards is filtered to those containing the name provided.
#>

Function Get-NRDashboardList {
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter ()]
    [string] $NameFilter
  )

  Begin {
    $URL = 'https://api.newrelic.com/graphql'

    # Create header for authorization
    $headers = @{
      'Api-Key' = $APIKey
    }
  }
  Process {
    $graphqlQuery = Get-GraphQLQueryGetDashboardList -NameFilter $NameFilter

    # Build the body of the API call using the query
    $body = @{
      query = $graphqlQuery
    } | ConvertTo-Json

    # Call API
    Return (Invoke-RestMethod -Uri $URL -Method 'Post' -Headers $Headers -Body $body -ContentType 'application/json').data.actor.entitysearch.results.entities
  }
}

<#
.Synopsis
  Creates a New Relic dashboard
.Description
  Creates a New Relic dashboard as specified by the provided dashboard configuration.
.Example
  New-NRDashboard -APIKey $apikey -AccountId '12345678' -DashboardConfig $DashboardConfig
  Creates a new dashboard in account 12345678 with the provided configuration.
.Example
  $MyDashboardId = (Get-NRDashboardList -APIKey $apikey -NameFilter 'MyDashboard').guid
  $DashboardConfig = Get-NRDashboard -APIKey $apikey -DashboardId $MyDashboardId
  New-NRDashboard -APIKey $apikey -AccountId '12345678' -DashboardConfig $DashboardConfig
  Creates a new dashboard using the configuration from 'MyDashboard'.
.Parameter APIKey
  This must be a 'Personal API Key'. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys.
.Parameter AccountId
  The New Relic account Id where the new dashboard will be created.
.Parameter DashboardConfig
  A PSCustomObject representing the entity configuration for a New Relic dashboard. For more information, see the New Relic article on exporting/importing dashboard via the API (https://docs.newrelic.com/docs/apis/nerdgraph/examples/export-import-dashboards-using-api/).
#>

Function New-NRDashboard {
  [CMDLetBinding(SupportsShouldProcess)]
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $AccountId,
    [Parameter (Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    [PSCustomObject] $DashboardConfig
  )

  Begin {
    $URL = 'https://api.newrelic.com/graphql'

    # Create header for authorization
    $headers = @{
      'Api-Key' = $APIKey
    }
  }
  Process {
    $graphqlQuery = Get-GraphQLQueryCreateDashboard -AccountId $AccountId

    # Build the body of the API call using the query
    $body = @{
      query     = $graphqlQuery
      variables = @{
        dashboard = $DashboardConfig
      }
    } | ConvertTo-Json -Depth 20

    # Call API
    If ($PSCmdlet.ShouldProcess('Create Dashboard')) {
      Return (Invoke-RestMethod -Uri $URL -Method 'Post' -Headers $Headers -ContentType 'application/json' -Body $body).data.dashboardcreate
    }
  }
}

<#
.Synopsis
  Deletes a New Relic dashboard
.Description
  Deletes the New Relic dashboard with the specified Id.
.Example
  Remove-NRDashboard -APIKey $apikey -DashboardId $MyDashboardId
  Deletes the New Relic dashboard with the Id specified in $MyDashboardId.
.Parameter APIKey
  This must be a 'Personal API Key'. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys.
.Parameter DashboardId
  GUID for the dashboard to be deleted.
#>

Function Remove-NRDashboard {
  [CMDLetBinding(SupportsShouldProcess)]
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter (Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $DashboardId
  )

  Begin {
    $URL = 'https://api.newrelic.com/graphql'

    # Create header for authorization
    $headers = @{
      'Api-Key' = $APIKey
    }
  }
  Process {
    $graphqlQuery = Get-GraphQLQueryDeleteDashboard -DashboardId $DashboardId

    # Build the body of the API call using the query
    $body = @{
      query     = $graphqlQuery
    } | ConvertTo-Json -Depth 4

    # Call API
    If ($PSCmdlet.ShouldProcess('Delete Dashboard')) {
      Return (Invoke-RestMethod -Uri $URL -Method 'Post' -Headers $Headers -ContentType 'application/json' -Body $body).data
    }
  }
}

<#
.Synopsis
  Restores a deleted New Relic dashboard
.Description
  Restores the deleted New Relic dashboard with the specified Id.
.Example
  Restore-NRDashboard -APIKey $apikey -DashboardId $MyDashboardId
  Restores the New Relic dashboard with the Id specified in $MyDashboardId.
.Parameter APIKey
  This must be a 'Personal API Key'. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys.
.Parameter DashboardId
  GUID for the dashboard to be restored.
#>

Function Restore-NRDashboard {
  [CMDLetBinding(SupportsShouldProcess)]
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter (Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $DashboardId
  )

  Begin {
    $URL = 'https://api.newrelic.com/graphql'

    # Create header for authorization
    $headers = @{
      'Api-Key' = $APIKey
    }
  }
  Process {
    $graphqlQuery = Get-GraphQLQueryUndeleteDashboard -DashboardId $DashboardId

    # Build the body of the API call using the query
    $body = @{
      query     = $graphqlQuery
    } | ConvertTo-Json -Depth 4

    # Call API
    If ($PSCmdlet.ShouldProcess('Restore Dashboard')) {
      Return (Invoke-RestMethod -Uri $URL -Method 'Post' -Headers $Headers -ContentType 'application/json' -Body $body).data
    }
  }
}

<#
.Synopsis
  Updates a New Relic dashboard
.Description
  Updates a New Relic dashboard as specified by the provided dashboard configuration. The dashboard will be updated to match the provided configuration.
.Example
  Update-NRDashboard -APIKey $apikey -AccountId '12345678' -DashboardConfig $DashboardConfig
  Updates a New Relic dashboard in account 12345678 with the provided configuration
.Example
  $MyDashboardId = (Get-NRDashboardList -APIKey $apikey -NameFilter 'MyDashboard').guid
  $DashboardConfig = Get-NRDashboard -APIKey $apikey -DashboardId $MyDashboardId
  $DashboardToUpdateId = (Get-NRDashboardList -APIKey $apikey -NameFilter 'DashboardToUpdate').guid
  Update-NRDashboard -APIKey $apikey -DashboardId $DashboardToUpdateId -DashboardConfig $DashboardConfig
  Gets the configuration from 'MyDashboard' and applies it to 'DashboardToUpdate'. Note: This example assumes dashboard names are unique across accounts.
.Parameter APIKey
  This must be a 'Personal API Key'. See more here: https://docs.newrelic.com/docs/apis/get-started/intro-apis/types-new-relic-api-keys.
.Parameter DashboardId
  GUID for the dashboard to be updated.
.Parameter DashboardConfig
  A PSCustomObject representing the entity configuration for a New Relic dashboard. For more information, see the New Relic article on exporting/importing dashboard via the API (https://docs.newrelic.com/docs/apis/nerdgraph/examples/export-import-dashboards-using-api/)
#>

Function Update-NRDashboard {
  [CMDLetBinding(SupportsShouldProcess)]
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter (Mandatory = $true)]
    [string] $DashboardId,
    [Parameter (Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    [PSCustomObject] $DashboardConfig
  )

  Begin {
    $URL = 'https://api.newrelic.com/graphql'

    # Create header for authorization
    $headers = @{
      'Api-Key' = $APIKey
    }
  }
  Process {
    $graphqlQuery = Get-GraphQLQueryUpdateDashboard -DashboardId $DashboardId

    # Build the body of the API call using the query
    $body = @{
      query     = $graphqlQuery
      variables = @{
        dashboard = $DashboardConfig
      }
    } | ConvertTo-Json -Depth 20

    # Call API
    If ($PSCmdlet.ShouldProcess('Update Dashboard')) {
      Return (Invoke-RestMethod -Uri $URL -Method 'Post' -Headers $Headers -ContentType 'application/json' -Body $body).data.dashboardUpdate
    }
  }
}

#############################################
# Internal Functions
#############################################

Function Update-NRDashboardWidgetAccountID {
  [CMDLetBinding(SupportsShouldProcess)]
  Param (
    [Parameter (Mandatory = $true)]
    [string] $AccountId,
    [Parameter (Mandatory = $true)]
    [PSCustomObject] $DashboardConfig
  )
  $dashboardConfigJSON = $DashboardConfig | ConvertTo-JSON -Depth 20
  $stringsToReplace = ($dashboardConfigJSON | select-string -pattern '"AccountId": (.*),' -AllMatches).matches.value | Select-Object -unique

  # Replace account Id strings
  If ($stringsToReplace -and $PSCmdlet.ShouldProcess('Update Dashboard Widget Account Numbers')) {
    Foreach ($string in $stringsToReplace) {
      $DashboardConfigJSON = $DashboardConfigJSON -replace ($string, "`"accountId`": $AccountId,")
    }
  }
  Return $DashboardConfigJSON | ConvertFrom-JSON -Depth 20
}