NewRelicPS.NRQLConditions.psm1

Using module .\NewRelicPS.GraphQLQueries.psm1

<#
.Synopsis
  Gets New Relic NRQL Conditions
.Description
  Gets all New Relic conditions in an account or returns a filtered list based on specified parameters. This command only works with NRQL condition types.
.Example
  Get-NRQLCondition -APIKey $APIKey -AccountId 12345678
  Gets information on all New Relic conditions in account 12345678 which the user with $ApiKey has access to
.Example
  Get-NRQLCondition -APIKey $APIKey -AccountId 12345678 -ConditionId 123
  Returns only data for the condition with id 123 in account 12345678 which the user with $ApiKey has access to
.Example
  Get-NRQLCondition -APIKey $APIKey -AccountId 12345678 -Type 'BASELINE'
  Returns all baseline conditions in the account 12345678 which the user with $ApiKey has access to
.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 assigned Id for the New Relic account containing conditions.
.Parameter ConditionId
  Filters results to the single condition with the Id specified. Returns null if a condition with the specified Id is not found.
.Parameter Name
  Filters results to conditions with the exact name specified. There may be multiple conditions with the same name.
.Parameter PolicyId
  Filters results to the conditions attached to the PolicyId specified.
.Parameter Type
  Filters results to the conditions of the type specified. Valid types are 'BASELINE', 'OUTLIER','STATIC'.
.Parameter Query
  Filters results to the conditions whose NRQL query exactly matches the query specified.
#>

Function Get-NRQLCondition {
  [CMDLetBinding()]
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $AccountId,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $ConditionId,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $Name,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $PolicyId,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('BASELINE', 'OUTLIER', 'STATIC')]
    [string] $Type,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $Query

  )
  Begin {
    $url = 'https://api.newrelic.com/graphql'
    $headers = @{
      'Api-Key' = $APIKey
    }
  }
  Process {
    # Build up the query filter from provided parameters
    $searchCriteria = @()
    Switch ($true) {
      { -NOT [string]::IsNullOrWhiteSpace($Name) } { $searchCriteria += "name: `"$Name`"" }
      { $PolicyId } { $searchCriteria += "policyId: $PolicyId" }
      { -NOT [string]::IsNullOrWhiteSpace($Query) } { $searchCriteria += "query: `"$Query`"" }
    }

    # GraphQl results are paginated, so gather all results before returning them.
    Do {

      $graphqlQuery = Get-GraphQLQueryGetNRQLCondition -AccountId $AccountId -SearchCriteria ($searchCriteria -join ' ') -NextCursor $nextCursor
      Write-Verbose "GraphQLQuery: `n$graphqlQuery"

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

      # Call the API
      $lastresult = (Invoke-RestMethod -Uri $url -headers $headers -body $body -Method 'Post' -ContentType 'application/json')

      # Return data or throw error, necessary so that errors do not get swallowed
      If ($lastresult.data) {
        [array]$results += $lastresult.data.actor.account.alerts.nrqlConditionsSearch.nrqlConditions
        $nextCursor = $lastresult.data.actor.account.alerts.nrqlConditionsSearch.nextCursor

        # The GraphQL search condition is very limited, so further filter results here if needed
        If ($ConditionId) {
          $results = $results | Where-Object { $_.id -eq $ConditionId }
        }
        If ($Type) {
          $results = $results | Where-Object { $_.type -eq $Type }
        }
      }
      ElseIf ($lastresult.errors) {
        Write-Error $lastresult.errors.message
      }
    } While ($null -ne $nextCursor)

    return $results
  }
}

<#
.Synopsis
  Creates a New Relic NRQL Condition
.Description
  Creates a New Relic NRQL Condition
.Example
  New-NRQLBaselineCondition -APIKey $APIKey -AccountId 12345678 -CriticalThreshold '100' -Name 'MyCondition' -PolicyId '4321' -Type 'Baseline' -Query 'SELECT count(*) FROM AwsLambdaInvocation'
  Creates a new NRQL baseline condition in account 12345678 on policy 4321 if the APIKey provided has access to create the condition
.Example
  New-NRQLBaselineCondition -APIKey $APIKey -AccountId 12345678 -WarningThreshold '90' -CriticalThreshold '100' -Name 'MyCondition' -PolicyId -Type 'Static' '4321' -Query 'SELECT count(*) FROM AwsLambdaInvocation'
  Creates a new NRQL static condition with both a warning and critical threshold in account 12345678 on policy 4321 if the APIKey provided has access to create the condition
.Example
  New-NRQLBaselineCondition -APIKey $APIKey -AccountId 12345678 -Enabled $false -CriticalThreshold '100' -Name 'MyCondition' -PolicyId '4321' -Type 'Baseline' -Query 'SELECT count(*) FROM AwsLambdaInvocation'
  Creates a new disabled NRQL baseline condition in account 12345678 on policy 4321 if the APIKey provided has access to create the condition
.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 assigned Id for the New Relic account containing conditions.
.Parameter CriticalThreshold
  The target value for creating an incident.
.Parameter Name
  The name given to the alert condition, it is possible to have multiple conditions with the same name on the same policy (an Id is assigned by New Relic on creation).
.Parameter PolicyId
  The New Relic assiged Id for the policy where the condition is created.
.Parameter Type
  The type of condition being updated. Valid values are Baseline, Outlier, Static.
.Parameter Query
  The NRQL query to run for the condition.
.Parameter Description
  A text description for the condition.
.Parameter BaselineDirection
  Determines whether the condition is evaluated on the upper limit, lower limit, or both. Valid values are 'UPPER_ONLY','LOWER_ONLY','UPPER_AND_LOWER'
.Parameter Enabled
  Specifies whether the condition should be created as enabled.
.Parameter RunbookURL
  Specifies the URL to the runbook for the condition being created.
.Parameter ExpectedGroups
  Specifies the number of expected groupings of returns values from an Outlier condition.
.Parameter EvaluationOffset
  This is the timeframe (in minutes) in which to evaluate the specified NRQL query (must be 1-120).
.Parameter ValueFunction
  Determines whether the condition is evaluated based on each query's returned value(SINGLE_VALUE) or on the sum of each query's returned values over the specified duration (SUM).
.Parameter ViolationTimeLimit
  Use to automatically close instance-based violations after the specified period. Valid values are 'ONE_HOUR','TWO_HOURS','FOUR_HOURS','EIGHT_HOURS','TWELVE_HOURS','TWENTY_FOUR_HOURS'.
.Parameter CriticalDuration
  This is the time (in seconds) for the condition to persist before triggering an event on the critical threshold.
.Parameter CriticalOperator
  This determines what comparison will be used between the value_function and the terms[threshold] value to trigger an event on the warning threshold. Valid values are 'ABOVE','BELOW','EQUAL'.
.Parameter CriticalOccurrences
  Determines whether an event is created when any data point within the duration crosses a threshold (ANY) or if ALL data points wthin the duration must cross the threshold to create an event. Valid values are 'ALL','ANY'.
.Parameter WarningDuration
  This is the time (in seconds) for the condition to persist before triggering an event on the warning threshold.
.Parameter WarningOperator
  This determines what comparison will be used between the value_function and the terms[threshold] value to trigger an event on the warning threshold. Valid values are 'ABOVE','BELOW','EQUAL'.
.Parameter WarningThredhold
  The target value for creating a warning event.
.Parameter WarningOccurrences
  Determines whether an event is created when any data point within the duration crosses a threshold (ANY) or if ALL data points wthin the duration must cross the threshold to create an event. Valid values are 'ALL','ANY'.
#>

Function New-NRQLCondition {
  [CMDLetBinding(SupportsShouldProcess = $true)]
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter (Mandatory = $true)]
    [string] $AccountId,
    [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $CriticalThreshold,
    [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $Name,
    [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $PolicyId,
    [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('Baseline','Outlier','Static')]
    [string] $Type,
    [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $Query,

    # Optional Parameters
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $Description = '',
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [boolean] $Enabled = $true,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string]$RunbookURL= '',
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [int] $ExpectedGroups = 1,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('UPPER_ONLY', 'LOWER_ONLY', 'UPPER_AND_LOWER')]
    [string] $BaselineDirection = 'UPPER_ONLY',
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $EvaluationOffset = '3',
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet('SINGLE_VALUE','SUM')]
    [string] $ValueFunction = 'SINGLE_VALUE',
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('ONE_HOUR', 'TWO_HOURS', 'FOUR_HOURS', 'EIGHT_HOURS', 'TWELVE_HOURS', 'TWENTY_FOUR_HOURS')]
    [string] $ViolationTimeLimit = 'TWENTY_FOUR_HOURS',

    # Optional Expiration Parameters
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [boolean] $CloseViolationsOnExpiration = $false,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $ExpirationDuration = '3600',
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [boolean] $OpenViolationOnExpiration = $false,

    # Optional Critical Threshold Parameters
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $CriticalDuration = '300',
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('ABOVE', 'BELOW', 'EQUAL')]
    [string] $CriticalOperator = 'ABOVE',
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('ALL', 'AT_LEAST_ONCE')]
    [string] $CriticalOccurrences = 'ALL',

    # Optional Warning Threshold Parameters
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $WarningDuration = '300',
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('ABOVE', 'BELOW', 'EQUAL')]
    [string] $WarningOperator = 'ABOVE',
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $WarningThreshold,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('ALL', 'AT_LEAST_ONCE')]
    [string] $WarningOccurrences = 'ALL'
  )
  Begin {
    $url = 'https://api.newrelic.com/graphql'
    $headers = @{
      'Api-Key' = $APIKey
    }
  }
  Process {

    # Terms specify the details of thresholds on conditions. A critical threshold is required and a warning threshold is optional.
    $Terms = "[{
      threshold: $CriticalThreshold
      thresholdDuration: $CriticalDuration
      thresholdOccurrences: $($CriticalOccurrences.ToUpper())
      operator: $($CriticalOperator.ToUpper())
      priority: CRITICAL
    }"


    # Only add a warning term if the user specifies a threshold for it
    If ($WarningThreshold) {
      $Terms += ", {
        threshold: $WarningThreshold
        thresholdDuration: $WarningDuration
        thresholdOccurrences: $($WarningOccurrences.ToUpper())
        operator: $($WarningOperator.ToUpper())
        priority: WARNING
      }"

    }

    # Add the terms closing bracket after determining if a warning threshold is specified
    $Terms += ']'

    # Build up params to create the QraphQL query
    $Params = @{
      AccountId                   = $AccountId
      Name                        = $Name
      PolicyId                    = $PolicyId
      Query                       = $Query
      Terms                       = $Terms
      CloseViolationsOnExpiration = $CloseViolationsOnExpiration
      Description                 = $Description
      Enabled                     = $Enabled
      RunbookURL                  = $RunbookURL
      ExpirationDuration          = $ExpirationDuration
      EvaluationOffset            = $EvaluationOffset
      OpenViolationOnExpiration   = $OpenViolationOnExpiration
      ViolationTimeLimit          = $ViolationTimeLimit.ToUpper()
    }

    # Determine the type of query based on condition type
    Switch ($Type) {
      'Baseline' {
        $queryType = 'alertsNrqlConditionBaselineCreate'
        $Params += @{
          QueryType = $queryType
          BaseLineDirection = $BaselineDirection.ToUpper()
        }
      }
      'Outlier' {
        $queryType = 'alertsNrqlConditionOutlierCreate'
        $Params += @{
          QueryType = $queryType
          ExpectedGroups = $ExpectedGroups

        }
      }
      'Static' {
        $queryType = 'alertsNrqlConditionStaticCreate'
        $Params += @{
          QueryType = $queryType
          ValueFunction = $ValueFunction
        }
      }
    }

    # Craft the body of the API call
    $graphqlQuery = Get-GraphQLQueryCreateNRQLCondition @Params
    Write-Verbose "GraphQLQuery: `n$graphqlQuery"
    $body = @{
      query = $graphqlQuery
    } | ConvertTo-Json

    # Call the API and return results
    If ($PSCmdlet.ShouldProcess($Name, 'Create NRQL Baseline Condition')) {
      $result = Invoke-RestMethod -Uri $url -headers $headers -body $body -Method 'Post' -ContentType 'application/json'

      If ($result.errors) {
        Write-Error ($result.errors | ConvertTo-Json -Depth 20)
      }
      return $result.data.$queryType
    }
  }
}

<#
.Synopsis
  Deletes a New Relic Condition
.Description
  You can use this CMDLet to delete any type of New Relic condition.
.Example
  Remove-NRQLCondition -APIKey $APIKey -AccountId 12345678 -ConditionId 1234
  Removes condition with ID 1234
.Example
  $ConditionsToDelete = Remove-NRQLCondition -APIKey $APIKey -AccountId 12345678
  Removes all conditons whose IDs are in the $ConditionsToDelete array
.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 assigned Id for the New Relic account containing conditions.
.Parameter ConditionId
  Filters results to the single condition with the Id specified. Returns null if a condition with the specified Id is not found.
#>

Function Remove-NRCondition {
  [CMDLetBinding(SupportsShouldProcess = $true)]
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $AccountId,
    [Parameter (Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $ConditionId
  )
  Begin {
    $url = 'https://api.newrelic.com/graphql'
    $headers = @{
      'Api-Key' = $APIKey
    }
  }
  Process {
    $graphqlQuery = Get-GraphQLQueryDeleteCondition -AccountId $AccountId -ConditionId $ConditionId
    Write-Verbose "GraphQLQuery: `n$graphqlQuery"
    $body = @{
      query = $graphqlQuery
    } | ConvertTo-Json

    # Call the API and return results
    If ($PSCmdlet.ShouldProcess($ConditionId, 'Delete NRQL Baseline Condition')) {
      $result = (Invoke-RestMethod -Uri $url -headers $headers -body $body -Method 'Post' -ContentType 'application/json')

      If ($result.errors) {
        Write-Error "$($result.errors.message) Is it possible the condition Id is incorrect?"

      }
      return $result.data.alertsConditionDelete
    }
  }
}

<#
.Synopsis
  Updates a New Relic NRQL Condition
.Description
  Updates one or many attributes of a New Relic NRQL Condition. Only the values provided are updated. Warning conditions can be removed by specifying an empty string for the WarningThreshold parameter (see examples).
.Example
  Update-NRQLCondition -APIKey $APIKey -AccountId 12345678 -ConditionId 112233 -Type 'Baseline' -CriticalThreshold '120'
  Updates a NRQL baseline condition with ID 112233 in account 12345678 with a critical threshold of 120 if the APIKey provided has access to update the condition.
.Example
  Update-NRQLCondition -APIKey $APIKey -AccountId 12345678 -ConditionId 112233 -Type 'Static' -WarningThreshold ''
  Removes the warning threshold from static condition 112233 in account 12345678 if the APIKey provided has access to update the condition.
.Example
  Update-NRQLCondition -APIKey $APIKey -AccountId 12345678 -ConditionId 112233 -Type 'Outlier' -Name 'MyRenamedCondition' -Query 'Select count(*) FROM myNewCustomRecord'
  Updates both the name and query of an the existing condition 112233 in account 12345678 if the APIKey provided has access to update the condition.
.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 assigned Id for the New Relic account containing conditions.
.Parameter ConditionId
  Filters results to the single condition with the Id specified. Returns null if a condition with the specified Id is not found.
.Parameter Type
  The type of condition being updated. Valid values are Baseline, Outlier, Static.
.Parameter BaselineDirection
  Determines whether the condition is evaluated on the upper limit, lower limit, or both. Valid values are 'UPPER_ONLY','LOWER_ONLY','UPPER_AND_LOWER'
.Parameter Description
  Provides a description for the condition
.Parameter Enabled
  Specifies whether the condition should be created as enabled.
.Parameter Name
  The name given to the alert condition, it is possible to have multiple conditions with the same name on the same policy (an Id is assigned by New Relic on creation).
.Parameter RunbookURL
  Specifies the URL to the runbook for the condition being created.
.Parameter ViolationTimeLimit
  Use to automatically close instance-based violations after the specified period. Valid values are 'ONE_HOUR','TWO_HOURS','FOUR_HOURS','EIGHT_HOURS','TWELVE_HOURS','TWENTY_FOUR_HOURS'.
.Parameter EvaluationOffset
  This is the timeframe (in minutes) in which to evaluate the specified NRQL query (must be 1-120).
.Parameter Query
  The NRQL query to run for the condition.
.Parameter CloseViolationsOnExpiration
  Determines if open violations expire after the expiration duration time period
.Parameter ExpirationDuration
  Sets the amount of time in seconds for violation expiration
.Parameter OpenViolationOnExpiration
  Determiens if a new violation should be opened following an expired one
.Parameter CriticalThreshold
  The target value for creating an incident.
.Parameter CriticalDuration
  This is the time (in seconds) for the condition to persist before triggering an event on the critical threshold.
.Parameter CriticalOperator
  This determines what comparison will be used between the value_function and the terms[threshold] value to trigger an event on the warning threshold. Valid values are 'ABOVE','BELOW','EQUAL'.
.Parameter CriticalOccurrences
  Determines whether an event is created when any data point within the duration crosses a threshold (ANY) or if ALL data points wthin the duration must cross the threshold to create an event. Valid values are 'ALL','ANY'.
.Parameter WarningDuration
  This is the time (in seconds) for the condition to persist before triggering an event on the warning threshold.
.Parameter WarningOperator
  This determines what comparison will be used between the value_function and the terms[threshold] value to trigger an event on the warning threshold. Valid values are 'ABOVE','BELOW','EQUAL'.
.Parameter WarningThredhold
  The target value for creating a warning event.
.Parameter WarningOccurrences
  Determines whether an event is created when any data point within the duration crosses a threshold (ANY) or if ALL data points wthin the duration must cross the threshold to create an event. Valid values are 'ALL','ANY'.
#>

Function Update-NRQLCondition {
  [CMDLetBinding(SupportsShouldProcess = $true)]
  Param (
    [Parameter (Mandatory = $true)]
    [string] $APIKey,
    [Parameter (Mandatory = $true)]
    [string] $AccountId,
    [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
    [string] $ConditionId,
    [Parameter (Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('Baseline','Static','Outlier')]
    [string] $Type,

    # Optional Parameters
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('UPPER_ONLY', 'LOWER_ONLY', 'UPPER_AND_LOWER')]
    [string] $BaselineDirection,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $Description,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [Nullable[boolean]] $Enabled,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $RunbookURL,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $Name,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('ONE_HOUR', 'TWO_HOURS', 'FOUR_HOURS', 'EIGHT_HOURS', 'TWELVE_HOURS', 'TWENTY_FOUR_HOURS')]
    [string] $ViolationTimeLimit,

    # Optional NRQL Parameters
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $EvaluationOffset,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $Query,

    # Expiration Parameters
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [Nullable[boolean]] $CloseViolationsOnExpiration,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $ExpirationDuration,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [Nullable[boolean]] $OpenViolationOnExpiration,

    # Optional Critical Threshold Parameters
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $CriticalThreshold,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $CriticalDuration,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('ABOVE', 'BELOW', 'EQUAL')]
    [string] $CriticalOperator,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('ALL', 'AT_LEAST_ONCE')]
    [string] $CriticalOccurrences,

    # Optional Warning Threshold Parameters
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $WarningDuration,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('ABOVE', 'BELOW', 'EQUAL')]
    [string] $WarningOperator,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [string] $WarningThreshold,
    [Parameter (ValueFromPipelineByPropertyName = $true)]
    [ValidateSet ('ALL', 'AT_LEAST_ONCE')]
    [string] $WarningOccurrences
  )
  Begin {
    $url = 'https://api.newrelic.com/graphql'
    $headers = @{
      'Api-Key' = $APIKey
    }
  }

  Process {

    # Build up the list of top-level fields to update
    $FieldsToUpdate = @()
    Switch ($true) {
      { $BaselineDirection } { $FieldsToUpdate += "baselineDirection: $($BaselineDirection.ToUpper())" }
      { -NOT [string]::IsNullOrWhiteSpace($Description) } { $FieldsToUpdate += "description: `"$Description`"" }
      { "$Enabled" } { $FieldsToUpdate += "enabled: $($Enabled.tostring().tolower())" }
      { -NOT [string]::IsNullOrWhiteSpace($Name) } { $FieldsToUpdate += "name: `"$Name`"" }
      { $ViolationTimeLimit } { $FieldsToUpdate += "violationTimeLimit: $ViolationTimeLimit" }
      { $RunbookURL} {$FieldsToUpdate += "runbookUrl: $RunbookURL"}
    }

    # If terms are being updated, get the existing condition and prepare the terms field update value
    If ($PSBoundParameters.keys -like "Critical*" -or $PSBoundParameters.keys -like "Warning*") {

      $existingCondition = Get-NRQLCondition -APIKey $APIKey -AccountId $AccountId -ConditionId $ConditionId
      If (-NOT $existingCondition) {
        Write-Error "Condition with Id $ConditionId was not found in account $AccountId. Does the provided API key have access?"
      }
      $existingWarningThreshold = $existingCondition.terms | Where-Object { $_.priority -eq 'WARNING' }
      $existingCriticalThreshold = $existingCondition.terms | Where-Object { $_.priority -eq 'CRITICAL' }

      # Build up the critical threshold, note that the GraphQL API requires all items to be provided for each term object in the terms array provided
      $Terms = "terms: [{
        threshold: $(($CriticalThreshold) ? $CriticalThreshold : $existingCriticalThreshold.threshold)
        thresholdDuration: $(($CriticalDuration) ? $CriticalDuration : $existingCriticalThreshold.thresholdDuration)
        thresholdOccurrences: $(($CriticalOccurrences) ? $($CriticalOccurrences.ToUpper()) : $existingCriticalThreshold.thresholdOccurrences)
        operator: $(($CriticalOperator) ? $($CriticalOperator.ToUpper()) : $existingCriticalThreshold.operator)
        priority: CRITICAL"


      # Update or add warning threshold if it is specified and WarningThreshold is not specified as an empty string
      If ($existingWarningThreshold -or $PSBoundParameters.keys -like "Warning*" -and $PSBoundParameters.WarningThreshold -ne '') {
        $Terms += "},{
          threshold: $(($WarningThreshold) ? $WarningThreshold : $existingWarningThreshold.threshold)
          thresholdDuration: $(($WarningDuration) ? $WarningDuration : $existingWarningThreshold.thresholdDuration)
          thresholdOccurrences: $(($WarningOccurrences) ? $($WarningOccurrences.ToUpper()) : $existingWarningThreshold.thresholdOccurrences)
          operator: $(($WarningOperator) ? $($WarningOperator.ToUpper()) : $existingWarningThreshold.operator)
          priority: WARNING"

      }

      # Close the term field
      $Terms += '}]'

      # Add terms to list of fields to update
      $FieldsToUpdate += $Terms
    }

    # Build up the list of expiration updates to send if any exist
    If ($PSBoundParameters.Keys -Like "*xpiration*") {
      $Expiration = 'expiration: {'
      Switch ($true) {
        { "$CloseViolationsOnExpiration" } { $Expiration += "closeViolationsOnExpiration: $($CloseViolationsOnExpiration.tostring().tolower()) " }
        { -NOT [string]::IsNullOrWhiteSpace($ExpirationDuration) } { $Expiration += "expirationDuration: $ExpirationDuration " }
        { "$OpenViolationOnExpiration" } { $Expiration += "openViolationOnExpiration: $($OpenViolationOnExpiration.tostring().tolower()) " }
      }

      # Close the expiration field
      $Expiration += '}'

      # Add expiration to the list of fields to update
      $FieldsToUpdate += $Expiration
    }

    # Build up the list of NRQL updates to send if any exist
    If ($Query -or $EvaluationOffset) {
      $nrql = 'nrql: {'
      Switch ($true) {
        {-NOT [string]::IsNullOrWhiteSpace($EvaluationOffset) } { $nrql += "evaluationOffset: $EvaluationOffset " }
        {-NOT  [string]::IsNullOrWhiteSpace($Query) } { $nrql += "query: `"$Query`"" }
      }

      # Close the NRQL field
      $nrql += '}'

      # Add nrql to the list of fields to update
      $FieldsToUpdate += $nrql
    }

    # Determine the type of query based on condition type
    Switch ($Type) {
      'Baseline' {$queryType = 'alertsNrqlConditionBaselineUpdate'}
      'Outlier' {$queryType = 'alertsNrqlConditionOutlierUpdate'}
      'Static' {$queryType = 'alertsNrqlConditionStaticUpdate'}
    }

    # Craft the body of the API call
    $graphqlQuery = Get-GraphQLQueryUpdateNRQLCondition -AccountId $AccountId -ConditionId $ConditionId -QueryType $QueryType -FieldsToUpdate ($FieldsToUpdate -Join ", ")
    Write-Verbose "GraphQLQuery: `n$graphqlQuery"
    $body = @{
      query = $graphqlQuery
    } | ConvertTo-Json

    # Call the API and return results
    If ($PSCmdlet.ShouldProcess($ConditionId, "Update NRQL $Type Condition")) {
      $result = (Invoke-RestMethod -Uri $url -headers $headers -body $body -Method 'Post' -ContentType 'application/json')

      If ($result.errors) {
        Write-Error ($result.errors | ConvertTo-Json -Depth 20)
      }
      return $result.data.$queryType
    }
  }
}