github.com/newrelic/newrelic-client-go@v1.1.0/pkg/alerts/nrql_conditions_integration_test.go (about)

     1  //go:build integration
     2  // +build integration
     3  
     4  package alerts
     5  
     6  import (
     7  	"fmt"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/newrelic/newrelic-client-go/pkg/errors"
    13  
    14  	mock "github.com/newrelic/newrelic-client-go/pkg/testhelpers"
    15  )
    16  
    17  var (
    18  	testNrqlConditionRandomString       = mock.RandSeq(5)
    19  	nrqlConditionBaseThreshold          = 1.0                                         // needed for setting pointer
    20  	nrqlConditionBaseThresholdZeroValue = float64(0)                                  // needed for setting pointer
    21  	nrqlConditionBaseSignalFillValue    = float64(0.1)                                // needed for setting pointer
    22  	nrqlConditionBaseExpirationDuration = 1200                                        // needed for setting pointer
    23  	nrqlConditionBaseEvalOffset         = 3                                           // needed for setting pointer
    24  	nrqlConditionBaseAggWindow          = 60                                          // needed for setting pointer
    25  	nrqlConditionBaseAggMethod          = NrqlConditionAggregationMethodTypes.Cadence // needed for setting pointer
    26  	nrqlConditionBaseAggDelay           = 2                                           // needed for setting pointer
    27  	nrqlConditionBaseAggTimer           = 5                                           // needed for setting pointer
    28  	nrqlConditionBaseSlideBy            = 30                                          // needed for setting pointer
    29  	nrqlConditionBaseValueFunction      = NrqlConditionValueFunctions.SingleValue     // needed for setting pointer
    30  
    31  	nrqlConditionCreateBase = NrqlConditionCreateBase{
    32  		Description: "test description",
    33  		Enabled:     true,
    34  		Name:        fmt.Sprintf("test-nrql-condition-%s", testNrqlConditionRandomString),
    35  		Nrql: NrqlConditionCreateQuery{
    36  			Query:            "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
    37  			EvaluationOffset: &nrqlConditionBaseEvalOffset,
    38  		},
    39  		RunbookURL: "test.com",
    40  		Terms: []NrqlConditionTerm{
    41  			{
    42  				Threshold:            &nrqlConditionBaseThreshold,
    43  				ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
    44  				ThresholdDuration:    600,
    45  				Operator:             AlertsNRQLConditionTermsOperatorTypes.ABOVE,
    46  				Priority:             NrqlConditionPriorities.Critical,
    47  			},
    48  		},
    49  		ViolationTimeLimitSeconds: 3600,
    50  		Expiration: &AlertsNrqlConditionExpiration{
    51  			CloseViolationsOnExpiration: true,
    52  			ExpirationDuration:          &nrqlConditionBaseExpirationDuration,
    53  			OpenViolationOnExpiration:   false,
    54  		},
    55  		Signal: &AlertsNrqlConditionCreateSignal{
    56  			AggregationWindow: &nrqlConditionBaseAggWindow,
    57  			EvaluationOffset:  &nrqlConditionBaseEvalOffset,
    58  			FillOption:        &AlertsFillOptionTypes.STATIC,
    59  			FillValue:         &nrqlConditionBaseSignalFillValue,
    60  		},
    61  	}
    62  
    63  	nrqlConditionUpdateBase = NrqlConditionUpdateBase{
    64  		Description: "test description",
    65  		Enabled:     true,
    66  		Name:        fmt.Sprintf("test-nrql-condition-%s", testNrqlConditionRandomString),
    67  		Nrql: NrqlConditionUpdateQuery{
    68  			Query:            "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
    69  			EvaluationOffset: &nrqlConditionBaseEvalOffset,
    70  		},
    71  		RunbookURL: "test.com",
    72  		Terms: []NrqlConditionTerm{
    73  			{
    74  				Threshold:            &nrqlConditionBaseThreshold,
    75  				ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
    76  				ThresholdDuration:    600,
    77  				Operator:             AlertsNRQLConditionTermsOperatorTypes.ABOVE,
    78  				Priority:             NrqlConditionPriorities.Critical,
    79  			},
    80  		},
    81  		ViolationTimeLimitSeconds: 3600,
    82  		Expiration: &AlertsNrqlConditionExpiration{
    83  			CloseViolationsOnExpiration: true,
    84  			ExpirationDuration:          &nrqlConditionBaseExpirationDuration,
    85  			OpenViolationOnExpiration:   false,
    86  		},
    87  		Signal: &AlertsNrqlConditionUpdateSignal{
    88  			AggregationWindow: &nrqlConditionBaseAggWindow,
    89  			EvaluationOffset:  &nrqlConditionBaseEvalOffset,
    90  			FillOption:        &AlertsFillOptionTypes.STATIC,
    91  			FillValue:         &nrqlConditionBaseSignalFillValue,
    92  		},
    93  	}
    94  
    95  	nrqlConditionCreateWithStreamingMethods = NrqlConditionCreateBase{
    96  		Description: "test description",
    97  		Enabled:     true,
    98  		Name:        fmt.Sprintf("test-nrql-condition-%s", testNrqlConditionRandomString),
    99  		Nrql: NrqlConditionCreateQuery{
   100  			Query: "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
   101  		},
   102  		RunbookURL: "test.com",
   103  		Terms: []NrqlConditionTerm{
   104  			{
   105  				Threshold:            &nrqlConditionBaseThreshold,
   106  				ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
   107  				ThresholdDuration:    600,
   108  				Operator:             AlertsNRQLConditionTermsOperatorTypes.ABOVE,
   109  				Priority:             NrqlConditionPriorities.Critical,
   110  			},
   111  		},
   112  		ViolationTimeLimitSeconds: 3600,
   113  		Expiration: &AlertsNrqlConditionExpiration{
   114  			CloseViolationsOnExpiration: true,
   115  			ExpirationDuration:          &nrqlConditionBaseExpirationDuration,
   116  			OpenViolationOnExpiration:   false,
   117  		},
   118  		Signal: &AlertsNrqlConditionCreateSignal{
   119  			AggregationWindow: &nrqlConditionBaseAggWindow,
   120  			FillOption:        &AlertsFillOptionTypes.STATIC,
   121  			FillValue:         &nrqlConditionBaseSignalFillValue,
   122  			AggregationMethod: &nrqlConditionBaseAggMethod,
   123  			AggregationDelay:  &nrqlConditionBaseAggDelay,
   124  		},
   125  	}
   126  
   127  	nrqlConditionUpdateWithStreamingMethods = NrqlConditionUpdateBase{
   128  		Description: "test description",
   129  		Enabled:     true,
   130  		Name:        fmt.Sprintf("test-nrql-condition-%s", testNrqlConditionRandomString),
   131  		Nrql: NrqlConditionUpdateQuery{
   132  			Query: "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
   133  		},
   134  		RunbookURL: "test.com",
   135  		Terms: []NrqlConditionTerm{
   136  			{
   137  				Threshold:            &nrqlConditionBaseThreshold,
   138  				ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
   139  				ThresholdDuration:    600,
   140  				Operator:             AlertsNRQLConditionTermsOperatorTypes.ABOVE,
   141  				Priority:             NrqlConditionPriorities.Critical,
   142  			},
   143  		},
   144  		ViolationTimeLimitSeconds: 3600,
   145  		Expiration: &AlertsNrqlConditionExpiration{
   146  			CloseViolationsOnExpiration: true,
   147  			ExpirationDuration:          &nrqlConditionBaseExpirationDuration,
   148  			OpenViolationOnExpiration:   false,
   149  		},
   150  		Signal: &AlertsNrqlConditionUpdateSignal{
   151  			AggregationWindow: &nrqlConditionBaseAggWindow,
   152  			FillOption:        &AlertsFillOptionTypes.STATIC,
   153  			FillValue:         &nrqlConditionBaseSignalFillValue,
   154  			AggregationMethod: &nrqlConditionBaseAggMethod,
   155  			AggregationDelay:  &nrqlConditionBaseAggDelay,
   156  		},
   157  	}
   158  
   159  	nrqlConditionCreateWithSlideBy = NrqlConditionCreateBase{
   160  		Description: "test description",
   161  		Enabled:     true,
   162  		Name:        fmt.Sprintf("test-nrql-condition-%s", testNrqlConditionRandomString),
   163  		Nrql: NrqlConditionCreateQuery{
   164  			Query: "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App' FACET OtherStuff",
   165  		},
   166  		RunbookURL: "test.com",
   167  		Terms: []NrqlConditionTerm{
   168  			{
   169  				Threshold:            &nrqlConditionBaseThreshold,
   170  				ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
   171  				ThresholdDuration:    600,
   172  				Operator:             AlertsNRQLConditionTermsOperatorTypes.ABOVE,
   173  				Priority:             NrqlConditionPriorities.Critical,
   174  			},
   175  		},
   176  		ViolationTimeLimitSeconds: 3600,
   177  		Expiration: &AlertsNrqlConditionExpiration{
   178  			CloseViolationsOnExpiration: true,
   179  			ExpirationDuration:          &nrqlConditionBaseExpirationDuration,
   180  			OpenViolationOnExpiration:   false,
   181  		},
   182  		Signal: &AlertsNrqlConditionCreateSignal{
   183  			AggregationWindow: &nrqlConditionBaseAggWindow,
   184  			FillOption:        &AlertsFillOptionTypes.STATIC,
   185  			FillValue:         &nrqlConditionBaseSignalFillValue,
   186  			AggregationMethod: &nrqlConditionBaseAggMethod,
   187  			AggregationDelay:  &nrqlConditionBaseAggDelay,
   188  			SlideBy:           &nrqlConditionBaseSlideBy,
   189  		},
   190  	}
   191  
   192  	nrqlConditionUpdateWithSlideBy = NrqlConditionUpdateBase{
   193  		Description: "test description",
   194  		Enabled:     true,
   195  		Name:        fmt.Sprintf("test-nrql-condition-%s", testNrqlConditionRandomString),
   196  		Nrql: NrqlConditionUpdateQuery{
   197  			Query: "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
   198  		},
   199  		RunbookURL: "test.com",
   200  		Terms: []NrqlConditionTerm{
   201  			{
   202  				Threshold:            &nrqlConditionBaseThreshold,
   203  				ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
   204  				ThresholdDuration:    600,
   205  				Operator:             AlertsNRQLConditionTermsOperatorTypes.ABOVE,
   206  				Priority:             NrqlConditionPriorities.Critical,
   207  			},
   208  		},
   209  		ViolationTimeLimitSeconds: 3600,
   210  		Expiration: &AlertsNrqlConditionExpiration{
   211  			CloseViolationsOnExpiration: true,
   212  			ExpirationDuration:          &nrqlConditionBaseExpirationDuration,
   213  			OpenViolationOnExpiration:   false,
   214  		},
   215  		Signal: &AlertsNrqlConditionUpdateSignal{
   216  			AggregationWindow: &nrqlConditionBaseAggWindow,
   217  			FillOption:        &AlertsFillOptionTypes.STATIC,
   218  			FillValue:         &nrqlConditionBaseSignalFillValue,
   219  			AggregationMethod: &nrqlConditionBaseAggMethod,
   220  			AggregationDelay:  &nrqlConditionBaseAggDelay,
   221  			SlideBy:           &nrqlConditionBaseSlideBy,
   222  		},
   223  	}
   224  )
   225  
   226  //REST API integration test (deprecated)
   227  func TestIntegrationNrqlConditions(t *testing.T) {
   228  	t.Parallel()
   229  
   230  	var (
   231  		randomString = mock.RandSeq(5)
   232  		alertPolicy  = Policy{
   233  			Name:               fmt.Sprintf("test-integration-nrql-policy-%s", randomString),
   234  			IncidentPreference: "PER_POLICY",
   235  		}
   236  		nrqlConditionName        = fmt.Sprintf("test-integration-nrql-condition-%s", randomString)
   237  		nrqlConditionNameUpdated = fmt.Sprintf("test-integration-nrql-condition-updated-%s", randomString)
   238  		nrqlCondition            = NrqlCondition{
   239  			Nrql: NrqlQuery{
   240  				Query:      "SELECT count(*) FROM Transactions",
   241  				SinceValue: "3",
   242  			},
   243  			Terms: []ConditionTerm{
   244  				{
   245  					Duration:     5,
   246  					Operator:     "above",
   247  					Priority:     "critical",
   248  					Threshold:    nrqlConditionBaseThreshold,
   249  					TimeFunction: "all",
   250  				},
   251  			},
   252  			Type:                "static",
   253  			Name:                nrqlConditionName,
   254  			RunbookURL:          "https://www.example.com",
   255  			ValueFunction:       "single_value",
   256  			ViolationCloseTimer: 3600,
   257  			Enabled:             true,
   258  		}
   259  	)
   260  
   261  	client := newIntegrationTestClient(t)
   262  
   263  	// Setup
   264  	policy, err := client.CreatePolicy(alertPolicy)
   265  
   266  	require.NoError(t, err)
   267  
   268  	// Deferred teardown
   269  	defer func() {
   270  		_, err := client.DeletePolicy(policy.ID)
   271  
   272  		if err != nil {
   273  			t.Logf("error cleaning up alert policy %d (%s): %s", policy.ID, policy.Name, err)
   274  		}
   275  	}()
   276  
   277  	// Test: Create
   278  	createResult, err := client.CreateNrqlCondition(policy.ID, nrqlCondition)
   279  
   280  	require.NoError(t, err)
   281  	require.NotNil(t, createResult)
   282  
   283  	// Test: List
   284  	listResult, err := client.ListNrqlConditions(policy.ID)
   285  
   286  	require.NoError(t, err)
   287  	require.Greater(t, len(listResult), 0)
   288  
   289  	// Test: Get
   290  	readResult, err := client.GetNrqlCondition(policy.ID, createResult.ID)
   291  
   292  	require.NoError(t, err)
   293  	require.NotNil(t, readResult)
   294  
   295  	// Test: Update
   296  	createResult.Name = nrqlConditionNameUpdated
   297  	updateResult, err := client.UpdateNrqlCondition(*createResult)
   298  
   299  	require.NoError(t, err)
   300  	require.NotNil(t, updateResult)
   301  	require.Equal(t, nrqlConditionNameUpdated, updateResult.Name)
   302  
   303  	// Test: Delete
   304  	result, err := client.DeleteNrqlCondition(updateResult.ID)
   305  
   306  	require.NoError(t, err)
   307  	require.NotNil(t, result)
   308  }
   309  
   310  func TestIntegrationNrqlConditions_Baseline(t *testing.T) {
   311  	t.Parallel()
   312  
   313  	testAccountID, err := mock.GetTestAccountID()
   314  	if err != nil {
   315  		t.Skipf("%s", err)
   316  	}
   317  
   318  	var (
   319  		randStr             = mock.RandSeq(5)
   320  		createBaselineInput = NrqlConditionCreateInput{
   321  			NrqlConditionCreateBase: nrqlConditionCreateWithSlideBy,
   322  			BaselineDirection:       &NrqlBaselineDirections.LowerOnly,
   323  		}
   324  		updateBaselineInput = NrqlConditionUpdateInput{
   325  			NrqlConditionUpdateBase: nrqlConditionUpdateWithSlideBy,
   326  			BaselineDirection:       &NrqlBaselineDirections.LowerOnly,
   327  		}
   328  	)
   329  
   330  	// Setup
   331  	client := newIntegrationTestClient(t)
   332  	testPolicy := AlertsPolicyInput{
   333  		IncidentPreference: AlertsIncidentPreferenceTypes.PER_POLICY,
   334  		Name:               fmt.Sprintf("test-alert-policy-%s", randStr),
   335  	}
   336  	policy, err := client.CreatePolicyMutation(testAccountID, testPolicy)
   337  	require.NoError(t, err)
   338  
   339  	// Test: Create (baseline condition)
   340  	created, err := client.CreateNrqlConditionBaselineMutation(testAccountID, policy.ID, createBaselineInput)
   341  	require.NoError(t, err)
   342  	require.NotNil(t, created)
   343  	require.NotNil(t, created.ID)
   344  	require.NotNil(t, created.PolicyID)
   345  	require.NotNil(t, created.Signal)
   346  	require.NotNil(t, created.Expiration)
   347  	require.Equal(t, NrqlConditionType("BASELINE"), created.Type)
   348  
   349  	// Test: Get (baseline condition)
   350  	require.NoError(t, err)
   351  	readResult, err := client.GetNrqlConditionQuery(testAccountID, created.ID)
   352  	require.NoError(t, err)
   353  	require.NotNil(t, readResult)
   354  	require.Equal(t, NrqlConditionType("BASELINE"), readResult.Type)
   355  	require.Equal(t, "test description", readResult.Description)
   356  
   357  	// Test: Update (baseline condition)
   358  	// There is currently a timing issue with this test.
   359  	// TODO: Once the upstream is fixed, test the updated fields to ensure the this worked
   360  	updateBaselineInput.Description = "test description updated"
   361  	_, err = client.UpdateNrqlConditionBaselineMutation(testAccountID, created.ID, updateBaselineInput)
   362  	require.NoError(t, err)
   363  
   364  	// Deferred teardown
   365  	defer func() {
   366  		_, err := client.DeletePolicyMutation(testAccountID, policy.ID)
   367  		if err != nil {
   368  			t.Logf("error cleaning up alert policy %s (%s): %s", policy.ID, policy.Name, err)
   369  		}
   370  	}()
   371  }
   372  
   373  func TestIntegrationNrqlConditions_Static(t *testing.T) {
   374  	t.Parallel()
   375  
   376  	testAccountID, err := mock.GetTestAccountID()
   377  	if err != nil {
   378  		t.Skipf("%s", err)
   379  	}
   380  
   381  	var (
   382  		randStr           = mock.RandSeq(5)
   383  		createStaticInput = NrqlConditionCreateInput{
   384  			NrqlConditionCreateBase: nrqlConditionCreateBase,
   385  			ValueFunction:           &NrqlConditionValueFunctions.SingleValue,
   386  		}
   387  		updateStaticInput = NrqlConditionUpdateInput{
   388  			NrqlConditionUpdateBase: nrqlConditionUpdateBase,
   389  			ValueFunction:           &NrqlConditionValueFunctions.SingleValue,
   390  		}
   391  	)
   392  
   393  	// Setup
   394  	client := newIntegrationTestClient(t)
   395  	testPolicy := AlertsPolicyInput{
   396  		IncidentPreference: AlertsIncidentPreferenceTypes.PER_POLICY,
   397  		Name:               fmt.Sprintf("test-alert-policy-%s", randStr),
   398  	}
   399  	policy, err := client.CreatePolicyMutation(testAccountID, testPolicy)
   400  	require.NoError(t, err)
   401  
   402  	// Test: Create (static condition)
   403  	createdStatic, err := client.CreateNrqlConditionStaticMutation(testAccountID, policy.ID, createStaticInput)
   404  	require.NoError(t, err)
   405  	require.NotNil(t, createdStatic)
   406  	require.NotNil(t, createdStatic.ID)
   407  	require.NotNil(t, createdStatic.PolicyID)
   408  	require.NotNil(t, createdStatic.Signal)
   409  	require.NotNil(t, createdStatic.Expiration)
   410  	require.Equal(t, NrqlConditionType("STATIC"), createdStatic.Type)
   411  
   412  	// Test: Get (static condition)
   413  	readResult, err := client.GetNrqlConditionQuery(testAccountID, createdStatic.ID)
   414  	require.NoError(t, err)
   415  	require.NotNil(t, readResult)
   416  	require.Equal(t, NrqlConditionType("STATIC"), readResult.Type)
   417  	require.Equal(t, "test description", readResult.Description)
   418  
   419  	// Test: Update (static condition)
   420  	// There is currently a timing issue with this test.
   421  	// TODO: Once the upstream is fixed, test the updated fields to ensure the this worked
   422  	updateStaticInput.Description = "test description updated"
   423  	_, err = client.UpdateNrqlConditionStaticMutation(testAccountID, readResult.ID, updateStaticInput)
   424  	require.NoError(t, err)
   425  
   426  	// Deferred teardown
   427  	defer func() {
   428  		_, err := client.DeletePolicyMutation(testAccountID, policy.ID)
   429  		if err != nil {
   430  			t.Logf("error cleaning up alert policy %s (%s): %s", policy.ID, policy.Name, err)
   431  		}
   432  	}()
   433  }
   434  
   435  func TestIntegrationNrqlConditions_ErrorScenarios(t *testing.T) {
   436  	t.Parallel()
   437  
   438  	testAccountID, err := mock.GetTestAccountID()
   439  	if err != nil {
   440  		t.Skipf("%s", err)
   441  	}
   442  
   443  	var (
   444  		randStr = mock.RandSeq(5)
   445  
   446  		// Invalid NrqlConditionCreateInput (Baseline and ValueFunction cannot exist together)
   447  		testInvalidMutationCreateInput = NrqlConditionCreateInput{
   448  			NrqlConditionCreateBase: nrqlConditionCreateBase,
   449  
   450  			// Having both of the following fields should result in an error returned from the API
   451  			BaselineDirection: &NrqlBaselineDirections.LowerOnly,
   452  			ValueFunction:     &NrqlConditionValueFunctions.SingleValue,
   453  		}
   454  
   455  		// Invalid NrqlConditionUpdateInput (Baseline and ValueFunction cannot exist together)
   456  		testInvalidMutationUpdateInput = NrqlConditionUpdateInput{
   457  			NrqlConditionUpdateBase: nrqlConditionUpdateBase,
   458  
   459  			// Having both of the following fields should result in an error returned from the API
   460  			BaselineDirection: &NrqlBaselineDirections.LowerOnly,
   461  			ValueFunction:     &NrqlConditionValueFunctions.SingleValue,
   462  		}
   463  	)
   464  
   465  	// Setup
   466  	client := newIntegrationTestClient(t)
   467  	testPolicy := AlertsPolicyInput{
   468  		IncidentPreference: AlertsIncidentPreferenceTypes.PER_POLICY,
   469  		Name:               fmt.Sprintf("test-alert-policy-%s", randStr),
   470  	}
   471  	policy, err := client.CreatePolicyMutation(testAccountID, testPolicy)
   472  	require.NoError(t, err)
   473  
   474  	// Test: Create Invalid (should result in an error)
   475  	createdBaseline, err := client.CreateNrqlConditionBaselineMutation(testAccountID, policy.ID, testInvalidMutationCreateInput)
   476  	require.Error(t, err)
   477  	require.Nil(t, createdBaseline)
   478  
   479  	// Test: Update Invalid (should result in an error)
   480  	updatedBaseline, err := client.UpdateNrqlConditionBaselineMutation(testAccountID, "8675309", testInvalidMutationUpdateInput)
   481  	require.Error(t, err)
   482  	require.Nil(t, updatedBaseline)
   483  
   484  	// Test: Create Invalid (should result in an error)
   485  	createdStatic, err := client.CreateNrqlConditionStaticMutation(testAccountID, policy.ID, testInvalidMutationCreateInput)
   486  	require.Error(t, err)
   487  	require.Nil(t, createdStatic)
   488  
   489  	// Test: Update Invalid (should result in an error)
   490  	updatedStatic, err := client.UpdateNrqlConditionStaticMutation(testAccountID, "8675309", testInvalidMutationUpdateInput)
   491  	require.Error(t, err)
   492  	require.Nil(t, updatedStatic)
   493  
   494  	// Test: 'Not Found' error for non-existent condition
   495  	_, err = client.GetNrqlConditionQuery(testAccountID, "999999999999999")
   496  	require.Error(t, err)
   497  	_, ok := err.(*errors.NotFound)
   498  	require.True(t, ok)
   499  
   500  	// Deferred teardown
   501  	defer func() {
   502  		_, err := client.DeletePolicyMutation(testAccountID, policy.ID)
   503  		if err != nil {
   504  			t.Logf("error cleaning up alert policy %s (%s): %s", policy.ID, policy.Name, err)
   505  		}
   506  	}()
   507  }
   508  
   509  func TestIntegrationNrqlConditions_Search(t *testing.T) {
   510  	t.Parallel()
   511  
   512  	testAccountID, err := mock.GetTestAccountID()
   513  	if err != nil {
   514  		t.Skipf("%s", err)
   515  	}
   516  
   517  	var (
   518  		randStr            = mock.RandSeq(5)
   519  		conditionName      = fmt.Sprintf("test-nrql-condition-%s", randStr)
   520  		thresholdCritical  = 1.0
   521  		testConditionInput = NrqlConditionCreateInput{
   522  			NrqlConditionCreateBase: NrqlConditionCreateBase{
   523  				Description: "test description",
   524  				Enabled:     true,
   525  				Name:        conditionName,
   526  				Nrql: NrqlConditionCreateQuery{
   527  					Query:            "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
   528  					EvaluationOffset: &nrqlConditionBaseEvalOffset,
   529  				},
   530  				RunbookURL: "test.com",
   531  				Terms: []NrqlConditionTerm{
   532  					{
   533  						Threshold:            &thresholdCritical,
   534  						ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
   535  						ThresholdDuration:    600,
   536  						Operator:             AlertsNRQLConditionTermsOperatorTypes.ABOVE,
   537  						Priority:             NrqlConditionPriorities.Critical,
   538  					},
   539  				},
   540  				ViolationTimeLimitSeconds: 3600,
   541  			},
   542  			BaselineDirection: &NrqlBaselineDirections.LowerOnly,
   543  		}
   544  		searchCriteria = NrqlConditionsSearchCriteria{
   545  			NameLike: conditionName,
   546  		}
   547  	)
   548  
   549  	client := newIntegrationTestClient(t)
   550  
   551  	// Setup
   552  	setupPolicy := AlertsPolicyInput{
   553  		IncidentPreference: AlertsIncidentPreferenceTypes.PER_POLICY,
   554  		Name:               fmt.Sprintf("test-alert-policy-%s", randStr),
   555  	}
   556  	policy, err := client.CreatePolicyMutation(testAccountID, setupPolicy)
   557  	require.NoError(t, err)
   558  
   559  	condition, err := client.CreateNrqlConditionBaselineMutation(testAccountID, policy.ID, testConditionInput)
   560  	require.NoError(t, err)
   561  	require.NotNil(t, condition)
   562  
   563  	// Test: Search
   564  	searchResults, err := client.SearchNrqlConditionsQuery(testAccountID, searchCriteria)
   565  	require.NoError(t, err)
   566  	require.Greater(t, len(searchResults), 0)
   567  
   568  	// Deferred teardown
   569  	defer func() {
   570  		_, err := client.DeletePolicyMutation(testAccountID, policy.ID)
   571  		if err != nil {
   572  			t.Logf("error cleaning up alert policy %s (%s): %s", policy.ID, policy.Name, err)
   573  		}
   574  	}()
   575  }
   576  
   577  func TestIntegrationNrqlConditions_CreateStatic(t *testing.T) {
   578  	t.Parallel()
   579  
   580  	testAccountID, err := mock.GetTestAccountID()
   581  	if err != nil {
   582  		t.Skipf("%s", err)
   583  	}
   584  
   585  	var (
   586  		randStr            = mock.RandSeq(5)
   587  		conditionName      = fmt.Sprintf("test-nrql-condition-%s", randStr)
   588  		testConditionInput = NrqlConditionCreateInput{
   589  			NrqlConditionCreateBase: NrqlConditionCreateBase{
   590  				Description: "test description",
   591  				Enabled:     true,
   592  				Name:        conditionName,
   593  				Nrql: NrqlConditionCreateQuery{
   594  					Query:            "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
   595  					EvaluationOffset: &nrqlConditionBaseEvalOffset,
   596  				},
   597  				RunbookURL: "test.com",
   598  				Terms: []NrqlConditionTerm{
   599  					{
   600  						Threshold:            &nrqlConditionBaseThreshold,
   601  						ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
   602  						ThresholdDuration:    600,
   603  						Operator:             AlertsNRQLConditionTermsOperatorTypes.ABOVE,
   604  						Priority:             NrqlConditionPriorities.Critical,
   605  					},
   606  					{
   607  						Threshold:            &nrqlConditionBaseThresholdZeroValue,
   608  						ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
   609  						ThresholdDuration:    600,
   610  						Operator:             AlertsNRQLConditionTermsOperatorTypes.EQUALS,
   611  						Priority:             NrqlConditionPriorities.Warning,
   612  					},
   613  				},
   614  				ViolationTimeLimitSeconds: 3600,
   615  			},
   616  			ValueFunction: &NrqlConditionValueFunctions.SingleValue,
   617  		}
   618  	)
   619  
   620  	client := newIntegrationTestClient(t)
   621  
   622  	// Setup
   623  	setupPolicy := AlertsPolicyInput{
   624  		IncidentPreference: AlertsIncidentPreferenceTypes.PER_POLICY,
   625  		Name:               fmt.Sprintf("test-alert-policy-%s", randStr),
   626  	}
   627  	policy, err := client.CreatePolicyMutation(testAccountID, setupPolicy)
   628  	require.NoError(t, err)
   629  
   630  	condition, err := client.CreateNrqlConditionStaticMutation(testAccountID, policy.ID, testConditionInput)
   631  	require.NoError(t, err)
   632  	require.NotNil(t, condition)
   633  
   634  	// Deferred teardown
   635  	defer func() {
   636  		_, err := client.DeletePolicyMutation(testAccountID, policy.ID)
   637  		if err != nil {
   638  			t.Logf("error cleaning up alert policy %s (%s): %s", policy.ID, policy.Name, err)
   639  		}
   640  	}()
   641  }
   642  
   643  func TestIntegrationNrqlConditions_ZeroValueThreshold(t *testing.T) {
   644  	t.Parallel()
   645  
   646  	testAccountID, err := mock.GetTestAccountID()
   647  	if err != nil {
   648  		t.Skipf("%s", err)
   649  	}
   650  
   651  	var (
   652  		randStr            = mock.RandSeq(5)
   653  		conditionName      = fmt.Sprintf("test-nrql-condition-%s", randStr)
   654  		testConditionInput = NrqlConditionCreateInput{
   655  			NrqlConditionCreateBase: NrqlConditionCreateBase{
   656  				Description: "test description",
   657  				Enabled:     true,
   658  				Name:        conditionName,
   659  				Nrql: NrqlConditionCreateQuery{
   660  					Query:            "SELECT rate(sum(apm.service.cpu.usertime.utilization), 1 second) * 100 as cpuUsage FROM Metric WHERE appName like 'Dummy App'",
   661  					EvaluationOffset: &nrqlConditionBaseEvalOffset,
   662  				},
   663  				RunbookURL: "test.com",
   664  				Terms: []NrqlConditionTerm{
   665  					{
   666  						Threshold:            &nrqlConditionBaseThresholdZeroValue,
   667  						ThresholdOccurrences: ThresholdOccurrences.AtLeastOnce,
   668  						ThresholdDuration:    600,
   669  						Operator:             AlertsNRQLConditionTermsOperatorTypes.ABOVE,
   670  						Priority:             NrqlConditionPriorities.Critical,
   671  					},
   672  				},
   673  				ViolationTimeLimitSeconds: 3600,
   674  			},
   675  			ValueFunction: &NrqlConditionValueFunctions.SingleValue,
   676  		}
   677  	)
   678  
   679  	client := newIntegrationTestClient(t)
   680  
   681  	// Setup
   682  	setupPolicy := AlertsPolicyInput{
   683  		IncidentPreference: AlertsIncidentPreferenceTypes.PER_POLICY,
   684  		Name:               fmt.Sprintf("test-alert-policy-%s", randStr),
   685  	}
   686  	policy, err := client.CreatePolicyMutation(testAccountID, setupPolicy)
   687  	require.NoError(t, err)
   688  
   689  	condition, err := client.CreateNrqlConditionStaticMutation(testAccountID, policy.ID, testConditionInput)
   690  	require.NoError(t, err)
   691  	require.NotNil(t, condition)
   692  
   693  	// Deferred teardown
   694  	defer func() {
   695  		_, err := client.DeletePolicyMutation(testAccountID, policy.ID)
   696  		if err != nil {
   697  			t.Logf("error cleaning up alert policy %s (%s): %s", policy.ID, policy.Name, err)
   698  		}
   699  	}()
   700  }
   701  
   702  func TestIntegrationNrqlConditions_StreamingMethods(t *testing.T) {
   703  	t.Parallel()
   704  
   705  	testAccountID, err := mock.GetTestAccountID()
   706  	if err != nil {
   707  		t.Skipf("%s", err)
   708  	}
   709  
   710  	var (
   711  		randStr                     = mock.RandSeq(5)
   712  		createStreamingMethodsInput = NrqlConditionCreateInput{
   713  			NrqlConditionCreateBase: nrqlConditionCreateWithStreamingMethods,
   714  			ValueFunction:           &NrqlConditionValueFunctions.SingleValue,
   715  		}
   716  		updateStreamingMethodsInput = NrqlConditionUpdateInput{
   717  			NrqlConditionUpdateBase: nrqlConditionUpdateWithStreamingMethods,
   718  			ValueFunction:           &NrqlConditionValueFunctions.SingleValue,
   719  		}
   720  	)
   721  
   722  	// Setup
   723  	client := newIntegrationTestClient(t)
   724  	testPolicy := AlertsPolicyInput{
   725  		IncidentPreference: AlertsIncidentPreferenceTypes.PER_POLICY,
   726  		Name:               fmt.Sprintf("test-alert-policy-%s", randStr),
   727  	}
   728  	policy, err := client.CreatePolicyMutation(testAccountID, testPolicy)
   729  	require.NoError(t, err)
   730  
   731  	// Test: Create (static condition with streaming methods fields)
   732  	createdStaticWithStreamingMethods, err := client.CreateNrqlConditionStaticMutation(testAccountID, policy.ID, createStreamingMethodsInput)
   733  	require.NoError(t, err)
   734  	require.NotNil(t, createdStaticWithStreamingMethods)
   735  	require.NotNil(t, createdStaticWithStreamingMethods.ID)
   736  	require.NotNil(t, createdStaticWithStreamingMethods.PolicyID)
   737  	require.NotNil(t, createdStaticWithStreamingMethods.Signal)
   738  	require.NotNil(t, createdStaticWithStreamingMethods.Expiration)
   739  	require.Equal(t, &nrqlConditionBaseAggMethod, createdStaticWithStreamingMethods.Signal.AggregationMethod)
   740  
   741  	// Test: Get (static condition with streaming methods fields)
   742  	readResult, err := client.GetNrqlConditionQuery(testAccountID, createdStaticWithStreamingMethods.ID)
   743  	require.NoError(t, err)
   744  	require.NotNil(t, readResult)
   745  	require.Equal(t, &nrqlConditionBaseAggMethod, readResult.Signal.AggregationMethod)
   746  	require.Equal(t, &nrqlConditionBaseAggDelay, readResult.Signal.AggregationDelay)
   747  	require.Nil(t, createdStaticWithStreamingMethods.Signal.AggregationTimer)
   748  
   749  	// Test: Not found
   750  	notFoundResult, err := client.GetNrqlConditionQuery(testAccountID, "1")
   751  	require.Error(t, err)
   752  	require.Nil(t, notFoundResult)
   753  	_, ok := err.(*errors.NotFound)
   754  	require.True(t, ok)
   755  
   756  	// Test: Update (static condition with streaming methods fields modified)
   757  	nrqlConditionBaseAggMethodUpdated := NrqlConditionAggregationMethodTypes.EventTimer // needed for setting pointer
   758  
   759  	updateStreamingMethodsInput.Signal.AggregationMethod = &nrqlConditionBaseAggMethodUpdated
   760  	updateStreamingMethodsInput.Signal.AggregationDelay = nil
   761  	updateStreamingMethodsInput.Signal.AggregationTimer = &nrqlConditionBaseAggTimer
   762  
   763  	updatedStaticWithStreamingMethods, err := client.UpdateNrqlConditionStaticMutation(testAccountID, readResult.ID, updateStreamingMethodsInput)
   764  	require.NoError(t, err)
   765  	require.Equal(t, &nrqlConditionBaseAggMethodUpdated, updatedStaticWithStreamingMethods.Signal.AggregationMethod)
   766  	require.Equal(t, &nrqlConditionBaseAggTimer, updatedStaticWithStreamingMethods.Signal.AggregationTimer)
   767  	require.Nil(t, updatedStaticWithStreamingMethods.Signal.AggregationDelay)
   768  
   769  	// Test: Update (static condition without streaming methods fields)
   770  	updateStreamingMethodsInput.Signal.AggregationMethod = nil
   771  	updateStreamingMethodsInput.Signal.AggregationDelay = nil
   772  	updateStreamingMethodsInput.Signal.AggregationTimer = nil
   773  	updateStreamingMethodsInput.Signal.EvaluationOffset = &nrqlConditionBaseEvalOffset
   774  
   775  	updatedStaticWithoutStreamingMethods, err := client.UpdateNrqlConditionStaticMutation(testAccountID, readResult.ID, updateStreamingMethodsInput)
   776  	require.NoError(t, err)
   777  	require.Nil(t, updatedStaticWithoutStreamingMethods.Signal.AggregationMethod)
   778  	require.Nil(t, updatedStaticWithoutStreamingMethods.Signal.AggregationDelay)
   779  	require.Nil(t, updatedStaticWithoutStreamingMethods.Signal.AggregationTimer)
   780  	require.Equal(t, &nrqlConditionBaseEvalOffset, updatedStaticWithoutStreamingMethods.Signal.EvaluationOffset)
   781  
   782  	// Deferred teardown
   783  	defer func() {
   784  		_, err := client.DeletePolicyMutation(testAccountID, policy.ID)
   785  		if err != nil {
   786  			t.Logf("error cleaning up alert policy %s (%s): %s", policy.ID, policy.Name, err)
   787  		}
   788  	}()
   789  }
   790  
   791  func TestIntegrationNrqlConditions_ValueFunctionOptional(t *testing.T) {
   792  	t.Parallel()
   793  
   794  	testAccountID, err := mock.GetTestAccountID()
   795  	if err != nil {
   796  		t.Skipf("%s", err)
   797  	}
   798  
   799  	var (
   800  		randStr                    = mock.RandSeq(5)
   801  		createNoValueFunctionInput = NrqlConditionCreateInput{
   802  			NrqlConditionCreateBase: nrqlConditionCreateBase,
   803  		}
   804  		updateToAddValueFunctionInput = NrqlConditionUpdateInput{
   805  			NrqlConditionUpdateBase: nrqlConditionUpdateBase,
   806  			ValueFunction:           &NrqlConditionValueFunctions.SingleValue,
   807  		}
   808  	)
   809  
   810  	// Setup
   811  	client := newIntegrationTestClient(t)
   812  	testPolicy := AlertsPolicyInput{
   813  		IncidentPreference: AlertsIncidentPreferenceTypes.PER_POLICY,
   814  		Name:               fmt.Sprintf("test-alert-policy-%s", randStr),
   815  	}
   816  	policy, err := client.CreatePolicyMutation(testAccountID, testPolicy)
   817  	require.NoError(t, err)
   818  
   819  	// Test: Create (static condition without value function)
   820  	createdStaticWithoutValueFunction, err := client.CreateNrqlConditionStaticMutation(testAccountID, policy.ID, createNoValueFunctionInput)
   821  	require.NoError(t, err)
   822  	require.NotNil(t, createdStaticWithoutValueFunction)
   823  	require.NotNil(t, createdStaticWithoutValueFunction.ID)
   824  	require.NotNil(t, createdStaticWithoutValueFunction.PolicyID)
   825  	// When static condition is created without value function, API returns single value as value function
   826  	require.Equal(t, &nrqlConditionBaseValueFunction, createdStaticWithoutValueFunction.ValueFunction)
   827  
   828  	// Test: Get (static condition without value function)
   829  	readResult, err := client.GetNrqlConditionQuery(testAccountID, createdStaticWithoutValueFunction.ID)
   830  	require.NoError(t, err)
   831  	require.NotNil(t, readResult)
   832  	// When static condition is created without value function, API returns single value as value function
   833  	require.Equal(t, &nrqlConditionBaseValueFunction, readResult.ValueFunction)
   834  
   835  	// Test: Update (static condition with value function)
   836  	nrqlConditionSumValueFunction := NrqlConditionValueFunctions.SingleValue // needed for setting pointer
   837  
   838  	updatedStaticWithValueFunction, err := client.UpdateNrqlConditionStaticMutation(testAccountID, readResult.ID, updateToAddValueFunctionInput)
   839  	require.NoError(t, err)
   840  	require.Equal(t, &nrqlConditionSumValueFunction, updatedStaticWithValueFunction.ValueFunction)
   841  
   842  	// Deferred teardown
   843  	defer func() {
   844  		_, err := client.DeletePolicyMutation(testAccountID, policy.ID)
   845  		if err != nil {
   846  			t.Logf("error cleaning up alert policy %s (%s): %s", policy.ID, policy.Name, err)
   847  		}
   848  	}()
   849  }