tests/Configuration.SyntheticMonitor.Tests.ps1

. '.\tests\testCases\SyntheticMonitors.ps1'

BeforeAll {
  Import-Module '.\NewRelicPS.Configuration.SyntheticMonitor.psm1' -Force
  Import-Module '.\NewRelicPS.SyntheticMonitors.psm1' -Force
  Import-Module '.\NewRelicPS.SyntheticLocationConditions.psm1' -Force
  $apiKey = 'FAKE-KEY'
}

Describe 'Synthetic Location Monitor Configuration' {
  $TestCases = Get-SyntheticMonitorTestCases
  Context 'Set-NRSyntheticLocationMonitorConfiguration Base Tests' {
    BeforeAll {
      Mock New-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {}
      Mock Remove-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {}
      Mock Update-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {}
      Mock Get-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {
        @(
          @{
            id = 1234
            name = 'Test1'
            type = 'SIMPLE'
            frequency = 30
            uri = 'https://some.net'
            locations = @('AWS_CA_CENTRAL_1','AWS_US_EAST_1','AWS_US_EAST_2','AWS_US_WEST_1','AWS_US_WEST_2')
            status = 'ENABLED'
            slaThreshold = 7
            options = @{
              verifySSL = $false
              bypassHEADRequest = $true
              treatRedirectAsFailure = $false
            }
          },
          @{
            id = 1235
            name = 'Test2'
            type = 'SIMPLE'
            frequency = 10
            uri = 'https://some.net'
            locations = @('AWS_US_WEST_1','AWS_US_WEST_2')
            status = 'ENABLED'
            slaThreshold = 7
            options = @{
              verifySSL = $false
              bypassHEADRequest = $true
              treatRedirectAsFailure = $false
            }
          }
        )
      }
    }
    It 'Does nothing when all defined properties match all existing properties on all monitors' {
      $definedMonitors = @(
        @{
          name = 'Test1'
          type = 'SIMPLE'
          frequency = 30
          uri = 'https://some.net'
          locations = @('AWS_CA_CENTRAL_1','AWS_US_EAST_1','AWS_US_EAST_2','AWS_US_WEST_1','AWS_US_WEST_2')
          status = 'ENABLED'
          slaThreshold = 7
        },
        @{
          name = 'Test2'
          type = 'SIMPLE'
          frequency = 10
          uri = 'https://some.net'
          locations = @('AWS_US_WEST_1','AWS_US_WEST_2')
          status = 'ENABLED'
          slaThreshold = 7
        }
      )

      Set-NRSyntheticLocationMonitorConfiguration -AdminAPIKey $apiKey -DefinedSyntheticMonitors $definedMonitors
      Assert-MockCalled New-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 0
      Assert-MockCalled Update-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 0
      Assert-MockCalled Remove-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 0

    }
    It 'Removes monitors that are not defined' {
      $definedMonitors = @(
        @{
          name = 'Test1'
          type = 'SIMPLE'
          frequency = 30
          uri = 'https://some.net'
          locations = @('AWS_CA_CENTRAL_1','AWS_US_EAST_1','AWS_US_EAST_2','AWS_US_WEST_1','AWS_US_WEST_2')
          status = 'ENABLED'
          slaThreshold = 7
        }
      )
      Set-NRSyntheticLocationMonitorConfiguration -AdminAPIKey $apiKey -DefinedSyntheticMonitors $definedMonitors
      Assert-MockCalled New-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 0
      Assert-MockCalled Update-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 0
      Assert-MockCalled Remove-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 1 -ParameterFilter {
        $id -eq 1235
      }
    }

    It 'Creates a new monitor when no existing monitor matches the defined monitors name' {
      $definedMonitors = @(
        @{
          name = 'Test1'
          type = 'SIMPLE'
          frequency = 30
          uri = 'https://some.net'
          locations = @('AWS_CA_CENTRAL_1','AWS_US_EAST_1','AWS_US_EAST_2','AWS_US_WEST_1','AWS_US_WEST_2')
          status = 'ENABLED'
          slaThreshold = 7
        },
        @{
          name = 'Test2'
          type = 'SIMPLE'
          frequency = 10
          uri = 'https://some.net'
          locations = @('AWS_US_WEST_1','AWS_US_WEST_2')
          status = 'ENABLED'
          slaThreshold = 7
        },
        @{
          name = 'Test3'
          type = 'SIMPLE'
          frequency = 10
          uri = 'https://some.net'
          locations = @('AWS_US_WEST_1','AWS_US_WEST_2')
          status = 'ENABLED'
          slaThreshold = 7
        }
      )

      Set-NRSyntheticLocationMonitorConfiguration -AdminAPIKey $apiKey -DefinedSyntheticMonitors $definedMonitors
      Assert-MockCalled New-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 1 -ParameterFilter {
        $name -eq 'Test3'
      }
      Assert-MockCalled Update-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 0
      Assert-MockCalled Remove-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 0
    }

    It 'Updates the monitor when property <propertyName> does not match' -TestCases $TestCases {

      # Mock the get command to only return one monitor for these tests
      Mock Get-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {
        @(
          @{
            id = 1234
            name = 'Test1'
            type = 'SIMPLE'
            frequency = 30
            uri = 'https://some.net'
            locations = @('AWS_CA_CENTRAL_1','AWS_US_EAST_1','AWS_US_EAST_2','AWS_US_WEST_1','AWS_US_WEST_2')
            status = 'ENABLED'
            slaThreshold = 7
            options = @{
              verifySSL = $false
              bypassHEADRequest = $true
              treatRedirectAsFailure = $false
            }
          }
        )
      }
      Mock Get-NRSyntheticMonitorScript -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {
        @{
          scriptText = 'ABC1234'
        }
      }

      Set-NRSyntheticLocationMonitorConfiguration -AdminAPIKey $apiKey -DefinedSyntheticMonitors $definedMonitors
      Assert-MockCalled New-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 0
      Assert-MockCalled Remove-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 0
      Assert-MockCalled Update-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 1 -ParameterFilter {
        (Get-Variable -Name $propertyName).value -eq $definedMonitors.$propertyName
      }
    }
  }
  Context 'Set-NRSyntheticLocationMonitorConfiguration Scripted Monitor Parameter Handling' {
    BeforeAll {
      $scriptVariables = @{
        ENVIRONMENT_DOMAIN_API='some.net'
        HEALTH_TENANT_NAME='Health'
        HEALTH_TENANT_USERNAME='user@some.net'
      }
      Mock New-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {}
      Mock Remove-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {}
      Mock Update-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {}
      Mock Update-NRSyntheticMonitorScript -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {}
      Mock Get-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {
        @(
          @{
            id = 1234
            name = 'Test1'
            type = 'SCRIPT_API'
            frequency = 30
            uri = 'https://some.net'
            locations = @('AWS_CA_CENTRAL_1','AWS_US_EAST_1','AWS_US_EAST_2','AWS_US_WEST_1','AWS_US_WEST_2')
            status = 'ENABLED'
          }
        )
      }
      Mock Get-NRSyntheticMonitorScript -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' {

        # Return script with templated values plugged in
        $scriptVariables = @{
          ENVIRONMENT_DOMAIN_API='some.net'
          HEALTH_TENANT_NAME='Health'
          HEALTH_TENANT_USERNAME='user@some.net'
        }
        $scriptContent = Get-Content '.\tests\resources\SyntheticMonitor.Script.js' -Raw
        Foreach ($key in $scriptVariables.keys) {
          $scriptContent = $scriptContent.replace("`${$key}", $ScriptVariables.$key)
        }
        Return [pscustomobject] @{
          scriptText = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($scriptContent))
        }
      }

      $definedMonitors = @(
        @{
          name = 'Test1'
          type = 'SCRIPT_API'
          frequency = 30
          uri = 'https://some.net'
          locations = @('AWS_CA_CENTRAL_1','AWS_US_EAST_1','AWS_US_EAST_2','AWS_US_WEST_1','AWS_US_WEST_2')
          status = 'ENABLED'
          scriptPath = '.\tests\resources\SyntheticMonitor.Script.js'
          scriptVariables = @{
            ENVIRONMENT_DOMAIN_API = 'some.net'
            HEALTH_TENANT_NAME = 'Health'
            HEALTH_TENANT_USERNAME = 'user@some.net'
          }
        }
      )
    }
    It 'Does not update the monitor when templated script content matches existing content ' {
      Set-NRSyntheticLocationMonitorConfiguration -AdminAPIKey $apiKey -DefinedSyntheticMonitors $definedMonitors
      Assert-MockCalled Get-NRSyntheticMonitorScript -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 1 -ParameterFilter {
        $Id -eq '1234'
      }
      Assert-MockCalled Update-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 0
    }

    It 'Updates the monitor when existing script content has templated content and new templated content does not match' {
      $definedMonitors[0].scriptVariables['ENVIRONMENT_DOMAIN_API'] = 'someother.net'
      Set-NRSyntheticLocationMonitorConfiguration -AdminAPIKey $apiKey -DefinedSyntheticMonitors $definedMonitors
      Assert-MockCalled Get-NRSyntheticMonitorScript -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 1
      Assert-MockCalled Update-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 1 -ParameterFilter {
        $Name -eq 'Test1'
      }
    }

    It 'Updates the monitor when existing script content has templated content but no parameters currently provided' {
      $definedMonitors[0].scriptVariables = @{}
      Set-NRSyntheticLocationMonitorConfiguration -AdminAPIKey $apiKey -DefinedSyntheticMonitors $definedMonitors
      Assert-MockCalled Get-NRSyntheticMonitorScript -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 1
      Assert-MockCalled Update-NRSyntheticMonitor -ModuleName 'NewRelicPS.Configuration.SyntheticMonitor' -Exactly 1 -ParameterFilter {
        $Name -eq 'Test1'
      }
    }
  }
}