From 4fabb737356a99614c726d27c164a14e0ef723d3 Mon Sep 17 00:00:00 2001 From: Ashish Agrawal Date: Fri, 8 Sep 2023 13:05:54 -0700 Subject: [PATCH] Add new tests for alerting dashboards (#832) Signed-off-by: Ashish Agrawal (cherry picked from commit 430048457d287c0acda26bd66e9fb1bc96e214be) --- ...sample_cluster_metrics_health_monitor.json | 58 ++++ .../sample_cluster_metrics_stats_monitor.json | 73 +++++ .../sample_composite_level_monitor.json | 274 ++++++++++++++++++ .../cluster_metrics_monitor_spec.js | 26 +- .../composite_level_monitor_spec.js | 191 ++++++++++++ .../monitors_dashboard_spec.js | 152 ++++++++++ .../query_level_monitor_spec.js | 11 +- .../alerting-dashboards-plugin/commands.js | 79 +++-- .../alerting-dashboards-plugin/constants.js | 1 + 9 files changed, 836 insertions(+), 29 deletions(-) create mode 100644 cypress/fixtures/plugins/alerting-dashboards-plugin/sample_cluster_metrics_health_monitor.json create mode 100644 cypress/fixtures/plugins/alerting-dashboards-plugin/sample_cluster_metrics_stats_monitor.json create mode 100644 cypress/fixtures/plugins/alerting-dashboards-plugin/sample_composite_level_monitor.json create mode 100644 cypress/integration/plugins/alerting-dashboards-plugin/composite_level_monitor_spec.js create mode 100644 cypress/integration/plugins/alerting-dashboards-plugin/monitors_dashboard_spec.js diff --git a/cypress/fixtures/plugins/alerting-dashboards-plugin/sample_cluster_metrics_health_monitor.json b/cypress/fixtures/plugins/alerting-dashboards-plugin/sample_cluster_metrics_health_monitor.json new file mode 100644 index 000000000..52ea935ed --- /dev/null +++ b/cypress/fixtures/plugins/alerting-dashboards-plugin/sample_cluster_metrics_health_monitor.json @@ -0,0 +1,58 @@ +{ + "name": "sample_cluster_metrics_health_monitor", + "type": "monitor", + "monitor_type": "cluster_metrics_monitor", + "enabled": true, + "schedule": { + "period": { + "unit": "MINUTES", + "interval": 1 + } + }, + "inputs": [ + { + "uri": { + "api_type": "CLUSTER_HEALTH", + "path": "_cluster/health/", + "path_params": "", + "url": "http://localhost:9200/_cluster/health/" + } + } + ], + "triggers": [], + "ui_metadata": { + "schedule": { + "timezone": null, + "frequency": "interval", + "period": { + "unit": "MINUTES", + "interval": 1 + }, + "daily": 0, + "weekly": { + "tue": false, + "wed": false, + "thur": false, + "sat": false, + "fri": false, + "mon": false, + "sun": false + }, + "monthly": { + "type": "day", + "day": 1 + }, + "cronExpression": "0 */1 * * *" + }, + "search": { + "searchType": "clusterMetrics", + "timeField": "", + "aggregations": [], + "groupBy": [], + "bucketValue": 1, + "bucketUnitOfTime": "h", + "filters": [] + }, + "monitor_type": "cluster_metrics_monitor" + } +} diff --git a/cypress/fixtures/plugins/alerting-dashboards-plugin/sample_cluster_metrics_stats_monitor.json b/cypress/fixtures/plugins/alerting-dashboards-plugin/sample_cluster_metrics_stats_monitor.json new file mode 100644 index 000000000..a258b0586 --- /dev/null +++ b/cypress/fixtures/plugins/alerting-dashboards-plugin/sample_cluster_metrics_stats_monitor.json @@ -0,0 +1,73 @@ +{ + "name": "sample_cluster_metrics_stats_monitor", + "type": "monitor", + "monitor_type": "cluster_metrics_monitor", + "enabled": true, + "schedule": { + "period": { + "unit": "MINUTES", + "interval": 1 + } + }, + "inputs": [ + { + "uri": { + "api_type": "CLUSTER_STATS", + "path": "_cluster/stats/", + "path_params": "", + "url": "http://localhost:9200/_cluster/stats/" + } + } + ], + "triggers": [ + { + "query_level_trigger": { + "id": "Y5mmA4kBIezNcMbMJnEy", + "name": "sample_cluster_metrics_stats_monitor-trigger1", + "severity": "1", + "condition": { + "script": { + "source": "ctx.results[0].indices.count >= 0", + "lang": "painless" + } + }, + "actions": [] + } + } + ], + "ui_metadata": { + "schedule": { + "timezone": null, + "frequency": "interval", + "period": { + "unit": "MINUTES", + "interval": 1 + }, + "daily": 0, + "weekly": { + "tue": false, + "wed": false, + "thur": false, + "sat": false, + "fri": false, + "mon": false, + "sun": false + }, + "monthly": { + "type": "day", + "day": 1 + }, + "cronExpression": "0 */1 * * *" + }, + "search": { + "searchType": "clusterMetrics", + "timeField": "", + "aggregations": [], + "groupBy": [], + "bucketValue": 1, + "bucketUnitOfTime": "h", + "filters": [] + }, + "monitor_type": "cluster_metrics_monitor" + } +} diff --git a/cypress/fixtures/plugins/alerting-dashboards-plugin/sample_composite_level_monitor.json b/cypress/fixtures/plugins/alerting-dashboards-plugin/sample_composite_level_monitor.json new file mode 100644 index 000000000..9b1f67bf4 --- /dev/null +++ b/cypress/fixtures/plugins/alerting-dashboards-plugin/sample_composite_level_monitor.json @@ -0,0 +1,274 @@ +{ + "sample_composite_monitor": { + "type": "workflow", + "schema_version": 0, + "name": "sampleComponentLevelMonitor", + "workflow_type": "composite", + "enabled": true, + "enabled_time": 1686908176848, + "schedule": { + "period": { + "interval": 1, + "unit": "MINUTES" + } + }, + "inputs": [ + { + "composite_input": { + "sequence": { + "delegates": [ + { + "order": 1, + "monitor_id": "qdYBw4gB2qeAWe54jQyZ" + }, + { + "order": 2, + "monitor_id": "rtYBw4gB2qeAWe54wAx5" + } + ] + } + } + } + ], + "triggers": [ + { + "chained_alert_trigger": { + "id": "pNaQw4gB2qeAWe54Fg2U", + "name": "sample_trigger", + "severity": "1", + "condition": { + "script": { + "source": "(monitor[id=qdYBw4gB2qeAWe54jQyZ]) && (monitor[id=rtYBw4gB2qeAWe54wAx5])", + "lang": "painless" + } + }, + "actions": [ + { + "id": "pdaQw4gB2qeAWe54Fg2U", + "name": "sample_channel", + "destination_id": "6dYFw4gB2qeAWe54NgyL", + "message_template": { + "source": "Monitor {{ctx.monitor.name}} just entered alert status. Please investigate the issue.\n - Trigger: {{ctx.trigger.name}}\n - Severity: {{ctx.trigger.severity}}\n - Period start: {{ctx.periodStart}}\n - Period end: {{ctx.periodEnd}}", + "lang": "mustache" + }, + "throttle_enabled": false, + "subject_template": { + "source": "Monitor {{ctx.monitor.name}} triggered an alert {{ctx.trigger.name}}", + "lang": "mustache" + } + } + ] + } + } + ], + "last_update_time": 1686908180116, + "owner": "alerting", + "monitor_type": "composite" + }, + "sample_composite_index": { + "mappings": { + "properties": { + "audit_category": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "audit_node_host_name": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "audit_node_id": { + "type": "text", + "fields": { + "keyword": { + "type": "keyword", + "ignore_above": 256 + } + } + } + } + } + }, + "sample_composite_associated_monitor_1": { + "name": "monitorOne", + "type": "monitor", + "monitor_type": "doc_level_monitor", + "enabled": false, + "schedule": { + "period": { + "unit": "MINUTES", + "interval": 1 + } + }, + "inputs": [ + { + "doc_level_input": { + "description": "", + "indices": ["sample_index_1"], + "queries": [ + { + "id": "monitor_1_query_1", + "name": "monitor_1_query_1", + "query": "NOT (audit_category:\"sample_text\")", + "tags": [] + }, + { + "id": "monitor_1_query_2", + "name": "monitor_1_query_2", + "query": "NOT (audit_node_host_name:\"sample_text\")", + "tags": [] + }, + { + "id": "monitor_1_query_3", + "name": "monitor_1_query_3", + "query": "NOT (audit_node_id:\"sample_text\")", + "tags": [] + } + ] + } + } + ], + "triggers": [ + { + "document_level_trigger": { + "id": "sample_trigger_id_1", + "name": "monitor_1_query_2", + "severity": "1", + "condition": { + "script": { + "source": "query[name=monitor_1_query_1] || query[name=monitor_1_query_2] && query[name=monitor_1_query_3]", + "lang": "painless" + } + }, + "actions": [] + } + } + ] + }, + "sample_composite_associated_monitor_2": { + "name": "monitorTwo", + "type": "monitor", + "monitor_type": "doc_level_monitor", + "enabled": false, + "schedule": { + "period": { + "unit": "MINUTES", + "interval": 1 + } + }, + "inputs": [ + { + "doc_level_input": { + "description": "", + "indices": ["sample_index_2"], + "queries": [ + { + "id": "monitor_2_query_1", + "name": "monitor_2_query_1", + "query": "NOT (audit_category:\"sample_text\")", + "tags": [] + }, + { + "id": "monitor_2_query_2", + "name": "monitor_2_query_2", + "query": "NOT (audit_node_host_name:\"sample_text\")", + "tags": [] + }, + { + "id": "monitor_2_query_3", + "name": "monitor_2_query_3", + "query": "NOT (audit_node_id:\"sample_text\")", + "tags": [] + } + ] + } + } + ], + "triggers": [ + { + "document_level_trigger": { + "id": "sample_trigger_2", + "name": "monitor_2_query_2", + "severity": "1", + "condition": { + "script": { + "source": "query[name=monitor_2_query_1] || query[name=monitor_2_query_2] && query[name=monitor_2_query_3]", + "lang": "painless" + } + }, + "actions": [] + } + } + ] + }, + "sample_composite_associated_monitor_3": { + "name": "monitorThree", + "type": "monitor", + "monitor_type": "doc_level_monitor", + "enabled": false, + "schedule": { + "period": { + "unit": "MINUTES", + "interval": 1 + } + }, + "inputs": [ + { + "doc_level_input": { + "description": "", + "indices": ["sample_index_2"], + "queries": [ + { + "id": "monitor_2_query_1", + "name": "monitor_2_query_1", + "query": "NOT (audit_category:\"sample_text\")", + "tags": [] + }, + { + "id": "monitor_2_query_2", + "name": "monitor_2_query_2", + "query": "NOT (audit_node_host_name:\"sample_text\")", + "tags": [] + }, + { + "id": "monitor_2_query_3", + "name": "monitor_2_query_3", + "query": "NOT (audit_node_id:\"sample_text\")", + "tags": [] + } + ] + } + } + ], + "triggers": [ + { + "document_level_trigger": { + "id": "sample_trigger_2", + "name": "monitor_2_query_2", + "severity": "1", + "condition": { + "script": { + "source": "query[name=monitor_2_query_1] || query[name=monitor_2_query_2] && query[name=monitor_2_query_3]", + "lang": "painless" + } + }, + "actions": [] + } + } + ] + }, + "sample_composite_associated_index_document": { + "audit_category": "FAILED_LOGIN", + "audit_node_host_name": "127.0.0.1", + "audit_node_id": "sample_node_id" + } +} diff --git a/cypress/integration/plugins/alerting-dashboards-plugin/cluster_metrics_monitor_spec.js b/cypress/integration/plugins/alerting-dashboards-plugin/cluster_metrics_monitor_spec.js index be3075ff4..9d6c165ec 100644 --- a/cypress/integration/plugins/alerting-dashboards-plugin/cluster_metrics_monitor_spec.js +++ b/cypress/integration/plugins/alerting-dashboards-plugin/cluster_metrics_monitor_spec.js @@ -105,10 +105,12 @@ describe('ClusterMetricsMonitor', () => { cy.contains('There are no existing monitors'); // Go to create monitor page - cy.contains('Create monitor').click(); + cy.contains('Create monitor', { timeout: 20000 }).click({ force: true }); // Select ClusterMetrics radio card - cy.get('[data-test-subj="clusterMetricsMonitorRadioCard"]').click(); + cy.get('[data-test-subj="clusterMetricsMonitorRadioCard"]').click({ + force: true, + }); // Wait for input to load and then type in the monitor name cy.get('input[name="name"]').type(SAMPLE_CLUSTER_METRICS_HEALTH_MONITOR); @@ -119,7 +121,7 @@ describe('ClusterMetricsMonitor', () => { ); // Confirm the Query parameters field is present and described as "optional" - cy.contains('Query parameters - optional'); + cy.contains('Path parameters - optional'); cy.get('[data-test-subj="clusterMetricsParamsFieldText"]'); // Press the 'Run for response' button @@ -144,7 +146,7 @@ describe('ClusterMetricsMonitor', () => { // .type('{downarrow}{enter}'); // Click the create button - cy.get('button').contains('Create').click(); + cy.get('button').contains('Create').click({ force: true }); // Confirm we can see only one row in the trigger list by checking element cy.contains('This table contains 1 row'); @@ -153,7 +155,7 @@ describe('ClusterMetricsMonitor', () => { cy.contains(SAMPLE_TRIGGER); // Go back to the Monitors list - cy.get('a').contains('Monitors').click(); + cy.get('a').contains('Monitors').click({ force: true }); // Confirm we can see the created monitor in the list cy.contains(SAMPLE_CLUSTER_METRICS_HEALTH_MONITOR); @@ -223,7 +225,7 @@ describe('ClusterMetricsMonitor', () => { }); }); - describe('displays Query parameters field appropriately', () => { + describe('displays Path parameters field appropriately', () => { beforeEach(() => { cy.deleteAllMonitors(); cy.reload(); @@ -234,10 +236,12 @@ describe('ClusterMetricsMonitor', () => { cy.contains('There are no existing monitors'); // Go to create monitor page - cy.contains('Create monitor').click(); + cy.contains('Create monitor', { timeout: 20000 }).click({ force: true }); // Select ClusterMetrics radio card - cy.get('[data-test-subj="clusterMetricsMonitorRadioCard"]').click(); + cy.get('[data-test-subj="clusterMetricsMonitorRadioCard"]').click({ + force: true, + }); // Wait for input to load and then type in the monitor name cy.get('input[name="name"]').type( @@ -249,9 +253,9 @@ describe('ClusterMetricsMonitor', () => { 'list snapshots{enter}' ); - // Confirm the Query parameters field is present and is not described as "optional" - cy.contains('Query parameters - optional').should('not.exist'); - cy.contains('Query parameters'); + // Confirm the Path parameters field is present and is not described as "optional" + cy.contains('Path parameters - optional').should('not.exist'); + cy.contains('Path parameters'); cy.get('[data-test-subj="clusterMetricsParamsFieldText"]'); }); }); diff --git a/cypress/integration/plugins/alerting-dashboards-plugin/composite_level_monitor_spec.js b/cypress/integration/plugins/alerting-dashboards-plugin/composite_level_monitor_spec.js new file mode 100644 index 000000000..fe1f47d87 --- /dev/null +++ b/cypress/integration/plugins/alerting-dashboards-plugin/composite_level_monitor_spec.js @@ -0,0 +1,191 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + ALERTING_API, + ALERTING_PLUGIN_NAME, +} from '../../../utils/plugins/alerting-dashboards-plugin/constants'; +import sampleCompositeJson from '../../../fixtures/plugins/alerting-dashboards-plugin/sample_composite_level_monitor.json'; +import * as _ from 'lodash'; +import { BASE_PATH } from '../../../utils/base_constants'; + +const sample_index_1 = 'sample_index_1'; +const sample_index_2 = 'sample_index_2'; +const SAMPLE_VISUAL_EDITOR_MONITOR = + 'sample_visual_editor_composite_level_monitor'; + +const clearAll = () => { + cy.deleteIndexByName(sample_index_1); + cy.deleteIndexByName(sample_index_2); + + cy.deleteAllAlerts(); + cy.deleteAllMonitors(); +}; + +describe('CompositeLevelMonitor', () => { + before(() => { + clearAll(); + + // Create indices + cy.createIndexByName( + sample_index_1, + sampleCompositeJson.sample_composite_index + ); + cy.createIndexByName( + sample_index_2, + sampleCompositeJson.sample_composite_index + ); + + // Create associated monitors + cy.createMonitor(sampleCompositeJson.sample_composite_associated_monitor_1); + cy.createMonitor(sampleCompositeJson.sample_composite_associated_monitor_2); + cy.createMonitor(sampleCompositeJson.sample_composite_associated_monitor_3); + }); + + beforeEach(() => { + // Set welcome screen tracking to false + localStorage.setItem('home:welcome:show', 'false'); + }); + + describe('can be created', () => { + beforeEach(() => { + // Visit Alerting OpenSearch Dashboards + cy.visit(`${BASE_PATH}/app/${ALERTING_PLUGIN_NAME}#/monitors`); + + // Common text to wait for to confirm page loaded, give up to 20 seconds for initial load + cy.contains('Create monitor', { timeout: 20000 }); + + // Go to create monitor page + cy.contains('Create monitor').click({ force: true }); + + // Select the Composite-Level Monitor type + cy.get('[data-test-subj="compositeLevelMonitorRadioCard"]').click({ + force: true, + }); + }); + + it('by visual editor', () => { + // Select visual editor for method of definition + cy.get('[data-test-subj="visualEditorRadioCard"]').click({ force: true }); + + // Wait for input to load and then type in the monitor name + cy.get('input[name="name"]').type(SAMPLE_VISUAL_EDITOR_MONITOR); + + // Select associated monitors + cy.get('[data-test-subj="monitors_list_0"]').type('monitorOne', { + delay: 50, + }); + cy.get('[title="monitorOne"]').click({ force: true }); + + cy.get('[data-test-subj="monitors_list_1"]').type('monitorTwo', { + delay: 50, + }); + cy.get('[title="monitorTwo"]').click({ force: true }); + + cy.get('button').contains('Add trigger').click({ force: true }); + + // Type trigger name + cy.get('[data-test-subj="composite-trigger-name"]') + .type('{selectall}') + .type('{backspace}') + .type('Composite trigger'); + + cy.intercept('api/alerting/workflows').as('createMonitorRequest'); + cy.intercept(`api/alerting/monitors?*`).as('getMonitorsRequest'); + cy.get('button').contains('Create').click({ force: true }); + + // Wait for monitor to be created + cy.wait('@createMonitorRequest').then(() => { + // Verify the monitor name on details page + cy.contains(SAMPLE_VISUAL_EDITOR_MONITOR); + + // Go back to the Monitors list + cy.get('a').contains('Monitors').click({ force: true }); + + cy.contains(SAMPLE_VISUAL_EDITOR_MONITOR); + }); + }); + }); + + describe('can be edited', () => { + beforeEach(() => { + const body = { + size: 200, + query: { + match_all: {}, + }, + }; + cy.request({ + method: 'GET', + url: `${Cypress.env('openSearchUrl')}${ + ALERTING_API.MONITOR_BASE + }/_search`, + failOnStatusCode: false, // In case there is no alerting config index in cluster, where the status code is 404 + body, + }).then((response) => { + if (response.status === 200) { + const monitors = response.body.hits.hits; + const createdMonitor = _.find( + monitors, + (monitor) => monitor._source.name === SAMPLE_VISUAL_EDITOR_MONITOR + ); + if (createdMonitor) { + cy.visit( + `${BASE_PATH}/app/${ALERTING_PLUGIN_NAME}#/monitors/${createdMonitor._id}?action=update-monitor&type=workflow` + ); + } else { + cy.log( + 'Failed to get created monitor ', + SAMPLE_VISUAL_EDITOR_MONITOR + ); + throw new Error( + `Failed to get created monitor ${SAMPLE_VISUAL_EDITOR_MONITOR}` + ); + } + } else { + cy.log('Failed to get all monitors.', response); + } + }); + }); + + it('by visual editor', () => { + // Verify edit page + cy.contains('Edit monitor', { timeout: 20000 }); + cy.get('input[name="name"]').type('_edited'); + + cy.get('label').contains('Visual editor').click({ force: true }); + + cy.get('button').contains('Add another monitor').click({ force: true }); + + cy.get('[data-test-subj="monitors_list_2"]').type('monitorThree', { + delay: 50, + }); + cy.get('[title="monitorThree"]').click({ force: true }); + + cy.get('button').contains('Composite trigger').click({ force: true }); + + cy.get('[data-test-subj="condition-add-options-btn_0"]').click({ + force: true, + }); + cy.get('[data-test-subj="select-expression_0_2"]').click({ force: true }); + cy.wait(1000); + cy.get('[data-test-subj="monitors-combobox-0-2"]') + .type('monitorThree', { delay: 50 }) + .type('{enter}'); + + cy.intercept('api/alerting/workflows/*').as('updateMonitorRequest'); + cy.get('button').contains('Update').click({ force: true }); + + // Wait for monitor to be created + cy.wait('@updateMonitorRequest').then(() => { + cy.get('.euiTitle--large').contains( + `${SAMPLE_VISUAL_EDITOR_MONITOR}_edited` + ); + }); + }); + }); + + after(() => clearAll()); +}); diff --git a/cypress/integration/plugins/alerting-dashboards-plugin/monitors_dashboard_spec.js b/cypress/integration/plugins/alerting-dashboards-plugin/monitors_dashboard_spec.js new file mode 100644 index 000000000..ba8898ee6 --- /dev/null +++ b/cypress/integration/plugins/alerting-dashboards-plugin/monitors_dashboard_spec.js @@ -0,0 +1,152 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { + ALERTING_INDEX, + ALERTING_PLUGIN_NAME, +} from '../../../utils/plugins/alerting-dashboards-plugin/constants'; +import sampleAlertsFlyoutBucketMonitor from '../../../fixtures/plugins/alerting-dashboards-plugin/sample_alerts_flyout_bucket_level_monitor.json'; +import sampleAlertsFlyoutQueryMonitor from '../../../fixtures/plugins/alerting-dashboards-plugin/sample_alerts_flyout_query_level_monitor.json'; +import sampleClusterMetricsHealthMonitor from '../../../fixtures/plugins/alerting-dashboards-plugin/sample_cluster_metrics_health_monitor.json'; +import sampleClusterMetricsStatsMonitor from '../../../fixtures/plugins/alerting-dashboards-plugin/sample_cluster_metrics_stats_monitor.json'; +import { BASE_PATH } from '../../../utils/base_constants'; + +const queryMonitor = { + ...sampleAlertsFlyoutQueryMonitor, + id: 'monitors_dashboard_cypress_query_level', + name: 'monitors_dashboard_cypress_query_level', + enabled: false, +}; +const bucketMonitor = { + ...sampleAlertsFlyoutBucketMonitor, + id: 'monitors_dashboard_cypress_bucket_level', + name: 'monitors_dashboard_cypress_bucket_level', + enabled: false, +}; +const clusterHealthMonitor = { + ...sampleClusterMetricsHealthMonitor, + id: 'monitors_dashboard_cypress_cluster_health', + name: 'monitors_dashboard_cypress_cluster_health', + enabled: false, + triggers: [ + { + query_level_trigger: { + id: 'WJmlA4kBIezNcMbMwnFg', + name: 'sample_cluster_metrics_health_monitor-trigger1', + severity: '1', + condition: { + script: { + source: 'ctx.results[0].status != "green"', + lang: 'painless', + }, + }, + actions: [], + }, + }, + ], +}; +const clusterStatsMonitor = { + ...sampleClusterMetricsStatsMonitor, + enabled: false, + id: 'monitors_dashboard_cypress_cluster_stats', + name: 'monitors_dashboard_cypress_cluster_stats', +}; +const testMonitors = [ + { + monitor: queryMonitor, + expectedAlertsCount: 1, + triggerName: queryMonitor.triggers[0].query_level_trigger.name, + }, + { + monitor: bucketMonitor, + expectedAlertsCount: 46, + triggerName: bucketMonitor.triggers[0].bucket_level_trigger.name, + }, + { + monitor: clusterHealthMonitor, + expectedAlertsCount: 1, + triggerName: clusterHealthMonitor.triggers[0].query_level_trigger.name, + }, + { + monitor: clusterStatsMonitor, + expectedAlertsCount: 1, + triggerName: clusterStatsMonitor.triggers[0].query_level_trigger.name, + }, +]; + +describe('Monitors dashboard page', () => { + before(() => { + // Delete any existing monitors + cy.deleteAllMonitors() + .then(() => { + // Load sample data + cy.loadSampleEcommerceData(); + }) + .then(() => { + // Short wait to reduce flakiness while ecommerce data is loaded + cy.wait(5000); + + // Create the test monitors + testMonitors.forEach((entry) => + cy.createAndExecuteMonitor(entry.monitor) + ); + }); + + // Visit Alerting OpenSearch Dashboards + cy.visit(`${BASE_PATH}/app/${ALERTING_PLUGIN_NAME}#/monitors`); + }); + + beforeEach(() => { + // Refresh Alerting OpenSearch Dashboards + cy.visit(`${BASE_PATH}/app/${ALERTING_PLUGIN_NAME}#/monitors`); + + // Common text to wait for to confirm page loaded, give up to 20 seconds for initial load + cy.contains('Create monitor', { timeout: 20000 }); + }); + + it('Displays expected number of alerts', () => { + // Ensure the 'Monitor name' column is sorted in ascending order by sorting another column first + cy.contains('Last updated by').click({ force: true }); + cy.contains('Monitor name').click({ force: true }); + + testMonitors.forEach((entry) => { + cy.get('tbody > tr') + .filter(`:contains(${entry.monitor.name})`, { timeout: 20000 }) + .within(() => { + cy.get('[class="euiTableRowCell"]') + .filter(':contains(Latest alert)', { timeout: 20000 }) + .should('contain', entry.triggerName); + + cy.get('[class="euiTableRowCell"]') + .filter(':contains(State)', { timeout: 20000 }) + .should('contain', 'Disabled'); + + cy.get('[class="euiTableRowCell"]') + .filter(':contains(Active)', { timeout: 20000 }) + .should('contain', entry.expectedAlertsCount); + + cy.get('[class="euiTableRowCell"]') + .filter(':contains(Acknowledged)', { timeout: 20000 }) + .should('contain', 0); + + cy.get('[class="euiTableRowCell"]') + .filter(':contains(Errors)', { timeout: 20000 }) + .should('contain', 0); + + cy.get('[class="euiTableRowCell"]') + .filter(':contains(Ignored)', { timeout: 20000 }) + .should('contain', 0); + }); + }); + }); + + after(() => { + // Delete all monitors + cy.deleteAllMonitors(); + + // Delete sample data + cy.deleteIndexByName(ALERTING_INDEX.SAMPLE_DATA_ECOMMERCE); + }); +}); diff --git a/cypress/integration/plugins/alerting-dashboards-plugin/query_level_monitor_spec.js b/cypress/integration/plugins/alerting-dashboards-plugin/query_level_monitor_spec.js index 9ff1aac74..5a7a9d858 100644 --- a/cypress/integration/plugins/alerting-dashboards-plugin/query_level_monitor_spec.js +++ b/cypress/integration/plugins/alerting-dashboards-plugin/query_level_monitor_spec.js @@ -34,7 +34,12 @@ const addVisualQueryLevelTrigger = ( thresholdValue ) => { // Click 'Add trigger' button - cy.contains('Add trigger', { timeout: 20000 }).click({ force: true }); + if (triggerIndex === 0) + cy.contains('Add trigger', { timeout: 20000 }).click({ force: true }); + else + cy.contains('Add another trigger', { timeout: 20000 }).click({ + force: true, + }); if (isEdit) { // TODO: Passing button props in EUI accordion was added in newer versions (31.7.0+). @@ -244,6 +249,10 @@ describe('Query-Level Monitors', () => { // Click the Delete button cy.contains('Delete').click({ force: true }); + cy.wait(1000); + cy.get('[data-test-subj="confirmModalConfirmButton"]').click({ + force: true, + }); // Confirm we can see an empty monitor list cy.contains('There are no existing monitors'); diff --git a/cypress/utils/plugins/alerting-dashboards-plugin/commands.js b/cypress/utils/plugins/alerting-dashboards-plugin/commands.js index 962566271..c0a49307a 100644 --- a/cypress/utils/plugins/alerting-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/alerting-dashboards-plugin/commands.js @@ -36,7 +36,7 @@ Cypress.Commands.add('createMonitor', (monitorJSON) => { 'POST', `${Cypress.env('openSearchUrl')}${ALERTING_API.MONITOR_BASE}`, monitorJSON - ); + ).then(({ body }) => body); }); Cypress.Commands.add('createAndExecuteMonitor', (monitorJSON) => { @@ -50,10 +50,43 @@ Cypress.Commands.add('createAndExecuteMonitor', (monitorJSON) => { `${Cypress.env('openSearchUrl')}${ALERTING_API.MONITOR_BASE}/${ response.body._id }/_execute` - ); + ).then(({ body }) => body); }); }); +Cypress.Commands.add('executeMonitor', (monitorID) => { + cy.request( + 'POST', + `${Cypress.env('openSearchUrl')}${ + ALERTING_API.MONITOR_BASE + }/${monitorID}/_execute` + ).then(({ body }) => body); +}); + +Cypress.Commands.add('executeCompositeMonitor', (monitorID) => { + cy.request( + 'POST', + `${Cypress.env('openSearchUrl')}${ + ALERTING_API.WORKFLOW_BASE + }/${monitorID}/_execute` + ).then(({ body }) => body); +}); + +Cypress.Commands.add('deleteAllAlerts', () => { + cy.request({ + method: 'POST', + url: `${Cypress.env( + 'openSearchUrl' + )}/.opendistro-alerting-alert*/_delete_by_query`, + body: { + query: { + match_all: {}, + }, + }, + failOnStatusCode: false, + }).then(({ body }) => body); +}); + Cypress.Commands.add('deleteMonitorByName', (monitorName) => { const body = { query: { @@ -75,7 +108,7 @@ Cypress.Commands.add('deleteMonitorByName', (monitorName) => { `${Cypress.env('openSearchUrl')}${ALERTING_API.MONITOR_BASE}/${ response.body.hits.hits[0]._id }` - ); + ).then(({ body }) => body); }); }); @@ -83,9 +116,7 @@ Cypress.Commands.add('deleteAllMonitors', () => { const body = { size: 200, query: { - exists: { - field: 'monitor', - }, + match_all: {}, }, }; cy.request({ @@ -95,13 +126,21 @@ Cypress.Commands.add('deleteAllMonitors', () => { body, }).then((response) => { if (response.status === 200) { - for (let i = 0; i < response.body.hits.total.value; i++) { - cy.request( - 'DELETE', - `${Cypress.env('openSearchUrl')}${ALERTING_API.MONITOR_BASE}/${ - response.body.hits.hits[i]._id - }` - ); + const monitors = response.body.hits.hits.sort((monitor) => + monitor._source.type === 'workflow' ? -1 : 1 + ); + for (let i = 0; i < monitors.length; i++) { + if (monitors[i]._id) { + cy.request({ + method: 'DELETE', + url: `${Cypress.env('openSearchUrl')}${ + monitors[i]._source.type === 'workflow' + ? ALERTING_API.WORKFLOW_BASE + : ALERTING_API.MONITOR_BASE + }/${monitors[i]._id}`, + failOnStatusCode: false, + }).then(({ body }) => body); + } } } else { cy.log('Failed to get all monitors.', response); @@ -110,11 +149,17 @@ Cypress.Commands.add('deleteAllMonitors', () => { }); Cypress.Commands.add('createIndexByName', (indexName) => { - cy.request('PUT', `${Cypress.env('openSearchUrl')}/${indexName}`); + cy.request('PUT', `${Cypress.env('openSearchUrl')}/${indexName}`).then( + ({ body }) => body + ); }); Cypress.Commands.add('deleteIndexByName', (indexName) => { - cy.request('DELETE', `${Cypress.env('openSearchUrl')}/${indexName}`); + cy.request({ + method: 'DELETE', + url: `${Cypress.env('openSearchUrl')}/${indexName}`, + failOnStatusCode: false, + }).then(({ body }) => body); }); Cypress.Commands.add( @@ -124,7 +169,7 @@ Cypress.Commands.add( 'POST', `${Cypress.env('openSearchUrl')}/${indexName}/_doc/${documentId}`, documentBody - ); + ).then(({ body }) => body); } ); @@ -133,5 +178,5 @@ Cypress.Commands.add('loadSampleEcommerceData', () => { method: 'POST', headers: { 'osd-xsrf': 'opensearch-dashboards' }, url: `${BASE_PATH}/api/sample_data/ecommerce`, - }); + }).then(({ body }) => body); }); diff --git a/cypress/utils/plugins/alerting-dashboards-plugin/constants.js b/cypress/utils/plugins/alerting-dashboards-plugin/constants.js index f4a1aad82..f2df921ac 100644 --- a/cypress/utils/plugins/alerting-dashboards-plugin/constants.js +++ b/cypress/utils/plugins/alerting-dashboards-plugin/constants.js @@ -12,6 +12,7 @@ export const ALERTING_INDEX = { export const ALERTING_API = { MONITOR_BASE: `${API_ROUTE_PREFIX}/monitors`, + WORKFLOW_BASE: `${API_ROUTE_PREFIX}/workflows`, DESTINATION_BASE: `${API_ROUTE_PREFIX}/destinations`, };