Merge branch 'exec-script' into backend
This commit is contained in:
13
src/components/ExecScriptButton/ExecScriptButton.tsx
Normal file
13
src/components/ExecScriptButton/ExecScriptButton.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import React, { FC } from 'react';
|
||||||
|
import { ActionButton } from '../ActionButton/ActionButton';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
className?: string;
|
||||||
|
onClick(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ExecScriptButton: FC<Props> = ({ className, onClick }) => {
|
||||||
|
return (
|
||||||
|
<ActionButton className={className} icon="terminal" tooltip="Execute script" onClick={onClick} />
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -2,5 +2,6 @@ export { GFHeartIcon } from './GFHeartIcon/GFHeartIcon';
|
|||||||
export { FAIcon } from './FAIcon/FAIcon';
|
export { FAIcon } from './FAIcon/FAIcon';
|
||||||
export { AckButton } from './AckButton/AckButton';
|
export { AckButton } from './AckButton/AckButton';
|
||||||
export { ExploreButton } from './ExploreButton/ExploreButton';
|
export { ExploreButton } from './ExploreButton/ExploreButton';
|
||||||
|
export { ExecScriptButton } from './ExecScriptButton/ExecScriptButton';
|
||||||
export { Tooltip } from './Tooltip/Tooltip';
|
export { Tooltip } from './Tooltip/Tooltip';
|
||||||
export { ModalController } from './Modal/ModalController';
|
export { ModalController } from './Modal/ModalController';
|
||||||
|
|||||||
@@ -37,6 +37,24 @@ export interface ZabbixRequestResponse {
|
|||||||
data?: JSONRPCResponse<any>;
|
data?: JSONRPCResponse<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ZabbixAPIResponse<T> = T;
|
export type ZabbixAPIResponse<T> = Promise<T>;
|
||||||
|
|
||||||
export type APILoginResponse = string;
|
export type APILoginResponse = string;
|
||||||
|
|
||||||
|
export interface ZBXScript {
|
||||||
|
scriptid: string;
|
||||||
|
name?: string;
|
||||||
|
command?: string;
|
||||||
|
host_access?: string;
|
||||||
|
usrgrpid?: string;
|
||||||
|
groupid?: string;
|
||||||
|
description?: string;
|
||||||
|
confirmation?: string;
|
||||||
|
type?: string;
|
||||||
|
execute_on?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface APIExecuteScriptResponse {
|
||||||
|
response: 'success' | 'failed';
|
||||||
|
value?: string;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import kbn from 'grafana/app/core/utils/kbn';
|
|||||||
import * as utils from '../../../utils';
|
import * as utils from '../../../utils';
|
||||||
import { ZBX_ACK_ACTION_NONE, ZBX_ACK_ACTION_ADD_MESSAGE, MIN_SLA_INTERVAL } from '../../../constants';
|
import { ZBX_ACK_ACTION_NONE, ZBX_ACK_ACTION_ADD_MESSAGE, MIN_SLA_INTERVAL } from '../../../constants';
|
||||||
import { ShowProblemTypes, ZBXProblem } from '../../../types';
|
import { ShowProblemTypes, ZBXProblem } from '../../../types';
|
||||||
import { GFHTTPRequest, JSONRPCError } from './types';
|
import { GFHTTPRequest, JSONRPCError, ZBXScript, APIExecuteScriptResponse } from './types';
|
||||||
import { getBackendSrv } from '@grafana/runtime';
|
import { getBackendSrv } from '@grafana/runtime';
|
||||||
|
|
||||||
const DEFAULT_ZABBIX_VERSION = '3.0.0';
|
const DEFAULT_ZABBIX_VERSION = '3.0.0';
|
||||||
@@ -629,6 +629,24 @@ export class ZabbixAPIConnector {
|
|||||||
|
|
||||||
return this.request('proxy.get', params);
|
return this.request('proxy.get', params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getScripts(hostids: string[], options?: any): Promise<ZBXScript[]> {
|
||||||
|
const params: any = {
|
||||||
|
output: 'extend',
|
||||||
|
hostids,
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('script.get', params).then(utils.mustArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
executeScript(hostid: string, scriptid: string): Promise<APIExecuteScriptResponse> {
|
||||||
|
const params: any = {
|
||||||
|
hostid,
|
||||||
|
scriptid,
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.request('script.execute', params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterTriggersByAcknowledge(triggers, acknowledged) {
|
function filterTriggersByAcknowledge(triggers, acknowledged) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ interface AppsResponse extends Array<any> {
|
|||||||
const REQUESTS_TO_PROXYFY = [
|
const REQUESTS_TO_PROXYFY = [
|
||||||
'getHistory', 'getTrend', 'getGroups', 'getHosts', 'getApps', 'getItems', 'getMacros', 'getItemsByIDs',
|
'getHistory', 'getTrend', 'getGroups', 'getHosts', 'getApps', 'getItems', 'getMacros', 'getItemsByIDs',
|
||||||
'getEvents', 'getAlerts', 'getHostAlerts', 'getAcknowledges', 'getITService', 'getSLA', 'getVersion', 'getProxies',
|
'getEvents', 'getAlerts', 'getHostAlerts', 'getAcknowledges', 'getITService', 'getSLA', 'getVersion', 'getProxies',
|
||||||
'getEventAlerts', 'getExtendedEventData', 'getProblems', 'getEventsHistory', 'getTriggersByIds'
|
'getEventAlerts', 'getExtendedEventData', 'getProblems', 'getEventsHistory', 'getTriggersByIds', 'getScripts'
|
||||||
];
|
];
|
||||||
|
|
||||||
const REQUESTS_TO_CACHE = [
|
const REQUESTS_TO_CACHE = [
|
||||||
@@ -30,7 +30,7 @@ const REQUESTS_TO_CACHE = [
|
|||||||
const REQUESTS_TO_BIND = [
|
const REQUESTS_TO_BIND = [
|
||||||
'getHistory', 'getTrend', 'getMacros', 'getItemsByIDs', 'getEvents', 'getAlerts', 'getHostAlerts',
|
'getHistory', 'getTrend', 'getMacros', 'getItemsByIDs', 'getEvents', 'getAlerts', 'getHostAlerts',
|
||||||
'getAcknowledges', 'getITService', 'getVersion', 'acknowledgeEvent', 'getProxies', 'getEventAlerts',
|
'getAcknowledges', 'getITService', 'getVersion', 'acknowledgeEvent', 'getProxies', 'getEventAlerts',
|
||||||
'getExtendedEventData'
|
'getExtendedEventData', 'getScripts', 'executeScript',
|
||||||
];
|
];
|
||||||
|
|
||||||
export class Zabbix implements ZabbixConnector {
|
export class Zabbix implements ZabbixConnector {
|
||||||
|
|||||||
226
src/panel-triggers/components/ExecScriptModal.tsx
Normal file
226
src/panel-triggers/components/ExecScriptModal.tsx
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
import { cx, css } from 'emotion';
|
||||||
|
import { ZBX_ACK_ACTION_ADD_MESSAGE, ZBX_ACK_ACTION_ACK, ZBX_ACK_ACTION_CHANGE_SEVERITY, ZBX_ACK_ACTION_CLOSE } from '../../datasource-zabbix/constants';
|
||||||
|
import { ZBXScript, APIExecuteScriptResponse } from '../../datasource-zabbix/zabbix/connectors/zabbix_api/types';
|
||||||
|
import { Button, Spinner, Modal, Select, stylesFactory, withTheme, Themeable } from '@grafana/ui';
|
||||||
|
import { GrafanaTheme, SelectableValue } from '@grafana/data';
|
||||||
|
import { FAIcon } from '../../components';
|
||||||
|
|
||||||
|
const KEYBOARD_ENTER_KEY = 13;
|
||||||
|
const KEYBOARD_ESCAPE_KEY = 27;
|
||||||
|
|
||||||
|
interface Props extends Themeable {
|
||||||
|
getScripts(): Promise<ZBXScript[]>;
|
||||||
|
onSubmit(data?: ExecScriptData): Promise<any> | any;
|
||||||
|
onDismiss?(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
selectedScript: SelectableValue<string>;
|
||||||
|
scriptOptions: Array<SelectableValue<string>>;
|
||||||
|
script: ZBXScript;
|
||||||
|
error: boolean;
|
||||||
|
errorMessage: string | JSX.Element;
|
||||||
|
result: string | JSX.Element;
|
||||||
|
selectError: string;
|
||||||
|
loading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ExecScriptData {
|
||||||
|
scriptid: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExecScriptModalUnthemed extends PureComponent<Props, State> {
|
||||||
|
scripts: ZBXScript[];
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
error: false,
|
||||||
|
errorMessage: '',
|
||||||
|
selectError: '',
|
||||||
|
selectedScript: null,
|
||||||
|
result: '',
|
||||||
|
loading: false,
|
||||||
|
scriptOptions: [],
|
||||||
|
script: null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async componentDidMount() {
|
||||||
|
const scripts = await this.props.getScripts();
|
||||||
|
this.scripts = scripts;
|
||||||
|
const scriptOptions: Array<SelectableValue<string>> = scripts.map(s => {
|
||||||
|
return {
|
||||||
|
value: s.scriptid,
|
||||||
|
label: s.name,
|
||||||
|
description: s.description || s.command,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const selectedScript = scriptOptions?.length ? scriptOptions[0] : null;
|
||||||
|
const script = scripts.find(s => selectedScript.value === s.scriptid);
|
||||||
|
|
||||||
|
this.setState({ scriptOptions, selectedScript, script });
|
||||||
|
}
|
||||||
|
|
||||||
|
onChangeSelectedScript = (v: SelectableValue<string>) => {
|
||||||
|
const script = this.scripts.find(s => v.value === s.scriptid);
|
||||||
|
this.setState({ selectedScript: v, script, errorMessage: '', loading: false, result: '' });
|
||||||
|
};
|
||||||
|
|
||||||
|
dismiss = () => {
|
||||||
|
this.setState({ selectedScript: null, error: false, errorMessage: '', selectError: '', loading: false });
|
||||||
|
this.props.onDismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
submit = () => {
|
||||||
|
const { selectedScript } = this.state;
|
||||||
|
|
||||||
|
if (!selectedScript) {
|
||||||
|
return this.setState({
|
||||||
|
selectError: 'Select a script to execute.'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ errorMessage: '', loading: true, result: '' });
|
||||||
|
|
||||||
|
const data: ExecScriptData = {
|
||||||
|
scriptid: selectedScript.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.props.onSubmit(data).then((result: APIExecuteScriptResponse) => {
|
||||||
|
const message = this.formatResult(result?.value || '');
|
||||||
|
if (result?.response === 'success') {
|
||||||
|
this.setState({ result: message, loading: false });
|
||||||
|
} else {
|
||||||
|
this.setState({ error: true, errorMessage: message, loading: false });
|
||||||
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
let errorMessage = err.message || err.data || '';
|
||||||
|
errorMessage = this.formatResult(errorMessage);
|
||||||
|
this.setState({
|
||||||
|
error: true,
|
||||||
|
loading: false,
|
||||||
|
errorMessage,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
formatResult = (result: string) => {
|
||||||
|
const formatted = result.split('\n').map((p, i) => {
|
||||||
|
return <p key={i}>{p}</p>;
|
||||||
|
});
|
||||||
|
return <>{formatted}</>;
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { theme } = this.props;
|
||||||
|
const { scriptOptions, selectedScript, script, result, selectError, errorMessage, error } = this.state;
|
||||||
|
|
||||||
|
const styles = getStyles(theme);
|
||||||
|
const modalClass = cx(styles.modal);
|
||||||
|
const modalTitleClass = cx(styles.modalHeaderTitle);
|
||||||
|
const selectErrorClass = cx('gf-form-hint-text', styles.inputError);
|
||||||
|
const scriptCommandContainerClass = cx('gf-form', styles.scriptCommandContainer);
|
||||||
|
const scriptCommandClass = cx('gf-form-hint-text', styles.scriptCommand);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal
|
||||||
|
isOpen={true}
|
||||||
|
onDismiss={this.dismiss}
|
||||||
|
className={modalClass}
|
||||||
|
title={
|
||||||
|
<div className={modalTitleClass}>
|
||||||
|
{this.state.loading ? <Spinner size={18} /> : <FAIcon icon="terminal" />}
|
||||||
|
<span className="p-l-1">Execute script</span>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<div className="gf-form">
|
||||||
|
<label className="gf-form-hint">
|
||||||
|
<Select
|
||||||
|
options={scriptOptions}
|
||||||
|
value={selectedScript}
|
||||||
|
onChange={this.onChangeSelectedScript}
|
||||||
|
/>
|
||||||
|
{selectError &&
|
||||||
|
<small className={selectErrorClass}>{selectError}</small>
|
||||||
|
}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div className={scriptCommandContainerClass}>
|
||||||
|
{script && <small className={scriptCommandClass}>{script.command}</small>}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className={styles.resultContainer}>
|
||||||
|
{result &&
|
||||||
|
<span className={styles.execResult}>{result}</span>
|
||||||
|
}
|
||||||
|
{error &&
|
||||||
|
<span className={styles.execError}>{errorMessage}</span>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="gf-form-button-row text-center">
|
||||||
|
<Button variant="primary" onClick={this.submit}>Execute</Button>
|
||||||
|
<Button variant="secondary" onClick={this.dismiss}>Cancel</Button>
|
||||||
|
</div>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||||
|
const red = theme.colors.red || (theme as any).palette.red;
|
||||||
|
return {
|
||||||
|
modal: css`
|
||||||
|
width: 600px;
|
||||||
|
`,
|
||||||
|
modalHeaderTitle: css`
|
||||||
|
font-size: ${theme.typography.heading.h3};
|
||||||
|
padding-top: ${theme.spacing.sm};
|
||||||
|
margin: 0 ${theme.spacing.md};
|
||||||
|
display: flex;
|
||||||
|
`,
|
||||||
|
input: css`
|
||||||
|
border-color: ${red};
|
||||||
|
border-radius: 2px;
|
||||||
|
outline-offset: 2px;
|
||||||
|
box-shadow: 0 0 0 2px ${theme.colors.pageBg || (theme as any).colors.bg1}, 0 0 0px 4px ${red};
|
||||||
|
`,
|
||||||
|
scriptCommandContainer: css`
|
||||||
|
margin-bottom: ${theme.spacing.md};
|
||||||
|
`,
|
||||||
|
scriptCommand: css`
|
||||||
|
color: ${theme.colors.textWeak};
|
||||||
|
text-align: left;
|
||||||
|
font-family: ${theme.typography.fontFamily.monospace};
|
||||||
|
`,
|
||||||
|
inputHint: css`
|
||||||
|
display: inherit;
|
||||||
|
float: right;
|
||||||
|
color: ${theme.colors.textWeak};
|
||||||
|
`,
|
||||||
|
inputError: css`
|
||||||
|
float: left;
|
||||||
|
color: ${red};
|
||||||
|
`,
|
||||||
|
resultContainer: css`
|
||||||
|
min-height: 50px;
|
||||||
|
font-family: ${theme.typography.fontFamily.monospace};
|
||||||
|
font-size: ${theme.typography.size.sm};
|
||||||
|
p {
|
||||||
|
font-size: ${theme.typography.size.sm};
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
execResult: css`
|
||||||
|
`,
|
||||||
|
execError: css`
|
||||||
|
color: ${red};
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
export const ExecScriptModal = withTheme(ExecScriptModalUnthemed);
|
||||||
@@ -2,13 +2,15 @@ import React, { PureComponent } from 'react';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import * as utils from '../../../datasource-zabbix/utils';
|
import * as utils from '../../../datasource-zabbix/utils';
|
||||||
import { ProblemDTO, ZBXHost, ZBXGroup, ZBXEvent, ZBXTag, ZBXAlert } from '../../../datasource-zabbix/types';
|
import { ProblemDTO, ZBXHost, ZBXGroup, ZBXEvent, ZBXTag, ZBXAlert } from '../../../datasource-zabbix/types';
|
||||||
|
import { ZBXScript, APIExecuteScriptResponse } from '../../../datasource-zabbix/zabbix/connectors/zabbix_api/types';
|
||||||
import { ZBXItem, GFTimeRange, RTRow } from '../../types';
|
import { ZBXItem, GFTimeRange, RTRow } from '../../types';
|
||||||
import { AckModal, AckProblemData } from '../AckModal';
|
import { AckModal, AckProblemData } from '../AckModal';
|
||||||
import EventTag from '../EventTag';
|
import EventTag from '../EventTag';
|
||||||
import ProblemStatusBar from './ProblemStatusBar';
|
import ProblemStatusBar from './ProblemStatusBar';
|
||||||
import AcknowledgesList from './AcknowledgesList';
|
import AcknowledgesList from './AcknowledgesList';
|
||||||
import ProblemTimeline from './ProblemTimeline';
|
import ProblemTimeline from './ProblemTimeline';
|
||||||
import { FAIcon, ExploreButton, AckButton, Tooltip, ModalController } from '../../../components';
|
import { FAIcon, ExploreButton, AckButton, Tooltip, ModalController, ExecScriptButton } from '../../../components';
|
||||||
|
import { ExecScriptModal, ExecScriptData } from '../ExecScriptModal';
|
||||||
|
|
||||||
interface ProblemDetailsProps extends RTRow<ProblemDTO> {
|
interface ProblemDetailsProps extends RTRow<ProblemDTO> {
|
||||||
rootWidth: number;
|
rootWidth: number;
|
||||||
@@ -17,6 +19,8 @@ interface ProblemDetailsProps extends RTRow<ProblemDTO> {
|
|||||||
panelId?: number;
|
panelId?: number;
|
||||||
getProblemEvents: (problem: ProblemDTO) => Promise<ZBXEvent[]>;
|
getProblemEvents: (problem: ProblemDTO) => Promise<ZBXEvent[]>;
|
||||||
getProblemAlerts: (problem: ProblemDTO) => Promise<ZBXAlert[]>;
|
getProblemAlerts: (problem: ProblemDTO) => Promise<ZBXAlert[]>;
|
||||||
|
getScripts: (problem: ProblemDTO) => Promise<ZBXScript[]>;
|
||||||
|
onExecuteScript(problem: ProblemDTO, scriptid: string): Promise<APIExecuteScriptResponse>;
|
||||||
onProblemAck?: (problem: ProblemDTO, data: AckProblemData) => Promise<any> | any;
|
onProblemAck?: (problem: ProblemDTO, data: AckProblemData) => Promise<any> | any;
|
||||||
onTagClick?: (tag: ZBXTag, datasource: string, ctrlKey?: boolean, shiftKey?: boolean) => void;
|
onTagClick?: (tag: ZBXTag, datasource: string, ctrlKey?: boolean, shiftKey?: boolean) => void;
|
||||||
}
|
}
|
||||||
@@ -74,6 +78,16 @@ export class ProblemDetails extends PureComponent<ProblemDetailsProps, ProblemDe
|
|||||||
return this.props.onProblemAck(problem, data);
|
return this.props.onProblemAck(problem, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getScripts = () => {
|
||||||
|
const problem = this.props.original as ProblemDTO;
|
||||||
|
return this.props.getScripts(problem);
|
||||||
|
}
|
||||||
|
|
||||||
|
onExecuteScript = (data: ExecScriptData) => {
|
||||||
|
const problem = this.props.original as ProblemDTO;
|
||||||
|
return this.props.onExecuteScript(problem, data.scriptid);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const problem = this.props.original as ProblemDTO;
|
const problem = this.props.original as ProblemDTO;
|
||||||
const alerts = this.state.alerts;
|
const alerts = this.state.alerts;
|
||||||
@@ -102,6 +116,20 @@ export class ProblemDetails extends PureComponent<ProblemDetailsProps, ProblemDe
|
|||||||
<ProblemStatusBar problem={problem} alerts={alerts} className={compactStatusBar && 'compact'} />
|
<ProblemStatusBar problem={problem} alerts={alerts} className={compactStatusBar && 'compact'} />
|
||||||
{problem.showAckButton &&
|
{problem.showAckButton &&
|
||||||
<div className="problem-actions">
|
<div className="problem-actions">
|
||||||
|
<ModalController>
|
||||||
|
{({ showModal, hideModal }) => (
|
||||||
|
<ExecScriptButton
|
||||||
|
className="navbar-button navbar-button--settings"
|
||||||
|
onClick={() => {
|
||||||
|
showModal(ExecScriptModal, {
|
||||||
|
getScripts: this.getScripts,
|
||||||
|
onSubmit: this.onExecuteScript,
|
||||||
|
onDismiss: hideModal,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</ModalController>
|
||||||
<ModalController>
|
<ModalController>
|
||||||
{({ showModal, hideModal }) => (
|
{({ showModal, hideModal }) => (
|
||||||
<AckButton
|
<AckButton
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import { AckProblemData } from '../AckModal';
|
|||||||
import { GFHeartIcon, FAIcon } from '../../../components';
|
import { GFHeartIcon, FAIcon } from '../../../components';
|
||||||
import { ProblemsPanelOptions, GFTimeRange, RTCell, TriggerSeverity, RTResized } from '../../types';
|
import { ProblemsPanelOptions, GFTimeRange, RTCell, TriggerSeverity, RTResized } from '../../types';
|
||||||
import { ProblemDTO, ZBXEvent, ZBXTag, ZBXAlert } from '../../../datasource-zabbix/types';
|
import { ProblemDTO, ZBXEvent, ZBXTag, ZBXAlert } from '../../../datasource-zabbix/types';
|
||||||
|
import { ZBXScript, APIExecuteScriptResponse } from '../../../datasource-zabbix/zabbix/connectors/zabbix_api/types';
|
||||||
import { AckCell } from './AckCell';
|
import { AckCell } from './AckCell';
|
||||||
|
|
||||||
export interface ProblemListProps {
|
export interface ProblemListProps {
|
||||||
@@ -22,6 +23,8 @@ export interface ProblemListProps {
|
|||||||
panelId?: number;
|
panelId?: number;
|
||||||
getProblemEvents: (problem: ProblemDTO) => Promise<ZBXEvent[]>;
|
getProblemEvents: (problem: ProblemDTO) => Promise<ZBXEvent[]>;
|
||||||
getProblemAlerts: (problem: ProblemDTO) => Promise<ZBXAlert[]>;
|
getProblemAlerts: (problem: ProblemDTO) => Promise<ZBXAlert[]>;
|
||||||
|
getScripts: (problem: ProblemDTO) => Promise<ZBXScript[]>;
|
||||||
|
onExecuteScript: (problem: ProblemDTO, scriptid: string) => Promise<APIExecuteScriptResponse>;
|
||||||
onProblemAck?: (problem: ProblemDTO, data: AckProblemData) => void;
|
onProblemAck?: (problem: ProblemDTO, data: AckProblemData) => void;
|
||||||
onTagClick?: (tag: ZBXTag, datasource: string, ctrlKey?: boolean, shiftKey?: boolean) => void;
|
onTagClick?: (tag: ZBXTag, datasource: string, ctrlKey?: boolean, shiftKey?: boolean) => void;
|
||||||
onPageSizeChange?: (pageSize: number, pageIndex: number) => void;
|
onPageSizeChange?: (pageSize: number, pageIndex: number) => void;
|
||||||
@@ -53,6 +56,9 @@ export default class ProblemList extends PureComponent<ProblemListProps, Problem
|
|||||||
return this.props.onProblemAck(problem, data);
|
return this.props.onProblemAck(problem, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onExecuteScript = (problem: ProblemDTO, data: AckProblemData) => {
|
||||||
|
}
|
||||||
|
|
||||||
handlePageSizeChange = (pageSize, pageIndex) => {
|
handlePageSizeChange = (pageSize, pageIndex) => {
|
||||||
if (this.props.onPageSizeChange) {
|
if (this.props.onPageSizeChange) {
|
||||||
this.props.onPageSizeChange(pageSize, pageIndex);
|
this.props.onPageSizeChange(pageSize, pageIndex);
|
||||||
@@ -170,7 +176,9 @@ export default class ProblemList extends PureComponent<ProblemListProps, Problem
|
|||||||
panelId={this.props.panelId}
|
panelId={this.props.panelId}
|
||||||
getProblemEvents={this.props.getProblemEvents}
|
getProblemEvents={this.props.getProblemEvents}
|
||||||
getProblemAlerts={this.props.getProblemAlerts}
|
getProblemAlerts={this.props.getProblemAlerts}
|
||||||
|
getScripts={this.props.getScripts}
|
||||||
onProblemAck={this.handleProblemAck}
|
onProblemAck={this.handleProblemAck}
|
||||||
|
onExecuteScript={this.props.onExecuteScript}
|
||||||
onTagClick={this.handleTagClick}
|
onTagClick={this.handleTagClick}
|
||||||
subRows={false}
|
subRows={false}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -316,6 +316,15 @@ export class TriggerPanelCtrl extends MetricsPanelCtrl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getProblemScripts(problem: ProblemDTO) {
|
||||||
|
const hostid = problem.hosts?.length ? problem.hosts[0].hostid : null;
|
||||||
|
|
||||||
|
return getDataSourceSrv().get(problem.datasource)
|
||||||
|
.then((datasource: any) => {
|
||||||
|
return datasource.zabbix.getScripts([hostid]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getAlertIconClassBySeverity(triggerSeverity) {
|
getAlertIconClassBySeverity(triggerSeverity) {
|
||||||
let iconClass = 'icon-gf-online';
|
let iconClass = 'icon-gf-online';
|
||||||
if (triggerSeverity.priority >= 2) {
|
if (triggerSeverity.priority >= 2) {
|
||||||
@@ -352,6 +361,15 @@ export class TriggerPanelCtrl extends MetricsPanelCtrl {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
executeScript(problem: ProblemDTO, scriptid: string) {
|
||||||
|
const hostid = problem.hosts?.length ? problem.hosts[0].hostid : null;
|
||||||
|
|
||||||
|
return getDataSourceSrv().get(problem.datasource)
|
||||||
|
.then((datasource: any) => {
|
||||||
|
return datasource.zabbix.executeScript(hostid, scriptid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
handlePageSizeChange(pageSize, pageIndex) {
|
handlePageSizeChange(pageSize, pageIndex) {
|
||||||
this.panel.pageSize = pageSize;
|
this.panel.pageSize = pageSize;
|
||||||
this.pageIndex = pageIndex;
|
this.pageIndex = pageIndex;
|
||||||
@@ -399,12 +417,14 @@ export class TriggerPanelCtrl extends MetricsPanelCtrl {
|
|||||||
panelId: ctrl.panel.id,
|
panelId: ctrl.panel.id,
|
||||||
getProblemEvents: ctrl.getProblemEvents.bind(ctrl),
|
getProblemEvents: ctrl.getProblemEvents.bind(ctrl),
|
||||||
getProblemAlerts: ctrl.getProblemAlerts.bind(ctrl),
|
getProblemAlerts: ctrl.getProblemAlerts.bind(ctrl),
|
||||||
|
getScripts: ctrl.getProblemScripts.bind(ctrl),
|
||||||
onPageSizeChange: ctrl.handlePageSizeChange.bind(ctrl),
|
onPageSizeChange: ctrl.handlePageSizeChange.bind(ctrl),
|
||||||
onColumnResize: ctrl.handleColumnResize.bind(ctrl),
|
onColumnResize: ctrl.handleColumnResize.bind(ctrl),
|
||||||
onProblemAck: (trigger, data) => {
|
onProblemAck: (trigger, data) => {
|
||||||
const { message, action, severity } = data;
|
const { message, action, severity } = data;
|
||||||
return ctrl.acknowledgeProblem(trigger, message, action, severity);
|
return ctrl.acknowledgeProblem(trigger, message, action, severity);
|
||||||
},
|
},
|
||||||
|
onExecuteScript: ctrl.executeScript.bind(ctrl),
|
||||||
onTagClick: (tag, datasource, ctrlKey, shiftKey) => {
|
onTagClick: (tag, datasource, ctrlKey, shiftKey) => {
|
||||||
if (ctrlKey || shiftKey) {
|
if (ctrlKey || shiftKey) {
|
||||||
ctrl.removeTagFilter(tag, datasource);
|
ctrl.removeTagFilter(tag, datasource);
|
||||||
|
|||||||
Reference in New Issue
Block a user