Skip to content

Commit

Permalink
[FEATURE] Add composite monitor type opensearch-project#573
Browse files Browse the repository at this point in the history
Signed-off-by: Jovan Cvetkovic <[email protected]>
  • Loading branch information
jovancvetkovic3006 committed Jun 21, 2023
1 parent 88d7ac9 commit 11ebb8d
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 96 deletions.
25 changes: 22 additions & 3 deletions cypress/integration/composite_level_monitor_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ describe('CompositeLevelMonitor', () => {
cy.contains('Create monitor', { timeout: 20000 });
});

let monitorId;
describe('can be created', () => {
beforeEach(() => {
// Go to create monitor page
Expand Down Expand Up @@ -88,7 +89,7 @@ describe('CompositeLevelMonitor', () => {

// Wait for monitor to be created
cy.wait('@createMonitorRequest').then((interceptor) => {
const monitorID = interceptor.response.body.resp._id;
monitorId = interceptor.response.body.resp._id;

cy.contains('Loading monitors');
cy.wait('@getMonitorsRequest').then((interceptor) => {
Expand All @@ -113,8 +114,7 @@ describe('CompositeLevelMonitor', () => {
);

cy.wait(1000).then(() => {
cy.executeCompositeMonitor(monitorID);
debugger;
cy.executeCompositeMonitor(monitorId);
monitor1[0] && cy.executeMonitor(monitor1[0].id);
monitor2[0] && cy.executeMonitor(monitor2[0].id);

Expand All @@ -127,5 +127,24 @@ describe('CompositeLevelMonitor', () => {
});
});

describe('can be edited', () => {
beforeEach(() => {
if (monitorId) {
cy.visit(
`${Cypress.env(
'opensearch_dashboards'
)}/app/${PLUGIN_NAME}#/monitors/${monitorId}?action=update-monitor&type=workflow`
);
} else {
throw new Error(`Monitor with ID: ${monitorId} not found or not created.`);
}
});

it('by visual editor', () => {
// Verify edit page
cy.contains('Edit monitor', { timeout: 20000 });
});
});

after(() => clearAll());
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,124 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React, { Fragment } from 'react';
import React, { Fragment, useState, useEffect, useCallback } from 'react';
import { EuiSpacer, EuiText } from '@elastic/eui';
import MonitorsList from './components/MonitorsList';
import { FormikCodeEditor } from '../../../../components/FormControls';
import * as _ from 'lodash';
import { isInvalid, hasError, validateExtractionQuery } from '../../../../utils/validate';

const AssociateMonitors = ({ monitors, options }) => {
const onUpdate = () => {};
const AssociateMonitors = ({
monitors,
options,
searchType = 'graph',
isDarkMode,
monitorValues,
}) => {
const [graphUi, setGraphUi] = useState(searchType === 'graph');

const queryTemplate = {
sequence: {
delegates: [],
},
};

const delegatesToMonitors = (value) =>
value.sequence.delegates.map((monitor) => ({
label: '',
value: monitor.monitor_id,
}));

useEffect(() => {
if (monitors?.length) {
const value = { ...queryTemplate };
monitors.map((monitor, idx) => {
let delegate = {
order: idx + 1,
monitor_id: monitor.monitor_id,
};
value.sequence.delegates.push(delegate);
_.set(monitorValues, `associatedMonitor_${idx}`, {
label: monitor.monitor_name || '',
value: monitor.monitor_id,
});
});

_.set(monitorValues, 'associatedMonitorsEditor', JSON.stringify(value, null, 4));
_.set(monitorValues, 'associatedMonitors', delegatesToMonitors(value));
} else {
if (options?.length) {
const value = { ...queryTemplate };
const firstTwo = options.slice(0, 2);
firstTwo.map((monitor, idx) => {
value.sequence.delegates.push({
order: idx + 1,
monitor_id: monitor.monitor_id,
});
});

try {
_.set(monitorValues, 'associatedMonitorsEditor', JSON.stringify(value, null, 4));
_.set(monitorValues, 'associatedMonitors', delegatesToMonitors(value));
} catch (e) {
console.log('No monitor options are available.');
}
}
}

setGraphUi(searchType === 'graph');
}, [searchType, monitors, options]);

const onCodeChange = useCallback(
(query, field, form) => {
form.setFieldValue('associatedMonitorsEditor', query);
try {
const code = JSON.parse(query);
form.setFieldValue('associatedMonitors', delegatesToMonitors(code));
} catch (e) {
console.error('Invalid json.');
}
},
[options, monitors]
);

return (
<Fragment>
<EuiText size={'m'} style={{ paddingBottom: '0px', marginBottom: '0px' }}>
<h4>Associate monitors</h4>
</EuiText>
<EuiText color={'subdued'} size={'xs'}>
Associate two or more monitors to run as part of this flow.
Associate two or more monitors to run as part of this workflow.
</EuiText>

<EuiSpacer size="m" />

<MonitorsList monitors={monitors} options={options} />
{graphUi ? (
<MonitorsList monitors={monitors} options={options} />
) : (
<FormikCodeEditor
name="associatedMonitorsEditor"
formRow
fieldProps={{
validate: validateExtractionQuery,
}}
rowProps={{
label: 'Define workflow',
fullWidth: true,
isInvalid,
error: hasError,
}}
inputProps={{
mode: 'json',
width: '80%',
height: '300px',
theme: isDarkMode ? 'sense-dark' : 'github',
onChange: onCodeChange,
onBlur: (e, field, form) => form.setFieldTouched('associatedMonitorsEditor', true),
'data-test-subj': 'associatedMonitorsCodeEditor',
}}
/>
)}
</Fragment>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ export default class CreateMonitor extends Component {
<EuiSpacer />

<WorkflowDetails
isDarkMode={isDarkMode}
values={values}
history={history}
isAd={values.searchType === SEARCH_TYPE.AD}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const getMonitors = async (httpClient) => {
}
};

const WorkflowDetails = ({ isAd, isComposite, httpClient, history, values }) => {
const WorkflowDetails = ({ isAd, isComposite, httpClient, history, values, isDarkMode }) => {
const [selectedMonitors, setSelectedMonitors] = useState([]);
const [monitorOptions, setMonitorOptions] = useState([]);

Expand All @@ -40,7 +40,7 @@ const WorkflowDetails = ({ isAd, isComposite, httpClient, history, values }) =>
setMonitorOptions(monitors);

const inputIds = values.inputs?.map((input) => input.monitor_id);
if (inputIds && inputIds.length) {
if (inputIds?.length) {
const selected = monitors.filter((monitor) => inputIds.indexOf(monitor.monitor_id) !== -1);
setSelectedMonitors(selected);
_.set(
Expand Down Expand Up @@ -70,7 +70,13 @@ const WorkflowDetails = ({ isAd, isComposite, httpClient, history, values }) =>
{isComposite && (
<Fragment>
<EuiSpacer size="xl" />
<AssociateMonitors monitors={selectedMonitors} options={monitorOptions} />
<AssociateMonitors
isDarkMode={isDarkMode}
monitors={selectedMonitors}
options={monitorOptions}
searchType={values.searchType}
monitorValues={values}
/>
</Fragment>
)}
</ContentPanel>
Expand Down
Loading

0 comments on commit 11ebb8d

Please sign in to comment.