Skip to content

Commit

Permalink
Feature: Zabbix service widget (#3905)
Browse files Browse the repository at this point in the history
Co-Authored-By: shamoon <[email protected]>
  • Loading branch information
ping-localhost and shamoon committed Aug 29, 2024
1 parent 4c6150a commit 44f8e9d
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 6 deletions.
27 changes: 26 additions & 1 deletion docs/widgets/authoring/proxies.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,21 @@ By default the key is passed as an `X-API-Key` header. If you need to pass the k

### `jsonrpcProxyHandler`

A proxy handler that makes authenticated JSON-RPC requests to the specified API endpoint. Where the endpoint is the method to call.
A proxy handler that makes authenticated JSON-RPC requests to the specified API endpoint, either using username + password or an API token.
The endpoint is the method to call and queryParams are used as the parameters.

=== "component.js"

```js
import Container from "components/services/widget/container";
import useWidgetAPI from "utils/proxy/use-widget-api";

export default function Component({ service }) {
const { widget } = service;

const { data, error } = useWidgetAPI(widget, 'trigger', { "triggerids": "14062", "output": "extend", "selectFunctions": "extend" });
}
```

=== "widget.js"

Expand All @@ -93,6 +107,7 @@ A proxy handler that makes authenticated JSON-RPC requests to the specified API
mappings: {
total: { endpoint: "total" },
average: { endpoint: "average" },
trigger: { endpoint: "trigger.get" },
},
};
```
Expand All @@ -110,6 +125,16 @@ A proxy handler that makes authenticated JSON-RPC requests to the specified API
password: your-password
```

```yaml
- Your Widget:
icon: yourwidget.svg
href: https://example.com/
widget:
type: yourwidget
url: http://127.0.0.1:1337
key: your-api-token
```

### `synologyProxyHandler`

A proxy handler that makes authenticated requests to the specified Synology API endpoint. This is used exclusively for Synology DSM services.
Expand Down
1 change: 1 addition & 0 deletions docs/widgets/services/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,4 @@ You can also find a list of all available service widgets in the sidebar navigat
- [WGEasy](wgeasy.md)
- [WhatsUpDocker](whatsupdocker.md)
- [xTeVe](xteve.md)
- [Zabbix](zabbix.md)
19 changes: 19 additions & 0 deletions docs/widgets/services/zabbix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
title: Zabbix
description: Zabbix Widget Configuration
---

Learn more about [Zabbix](https://github.com/zabbix/zabbix).

See the [Zabbix documentation](https://www.zabbix.com/documentation/current/en/manual/web_interface/frontend_sections/users/api_tokens) for details on generating API tokens.

The widget supports (at least) Zibbax server version 7.0.

Allowed fields: `["warning", "average", "high", "disaster"]`.

```yaml
widget:
type: zabbix
url: http://zabbix.host.or.ip/zabbix
key: your-api-key
```
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ nav:
- widgets/services/wgeasy.md
- widgets/services/whatsupdocker.md
- widgets/services/xteve.md
- widgets/services/zabbix.md
- "Information Widgets":
- widgets/info/index.md
- widgets/info/datetime.md
Expand Down
6 changes: 6 additions & 0 deletions public/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -931,5 +931,11 @@
"links": "Links",
"collections": "Collections",
"tags": "Tags"
},
"zabbix": {
"warning": "Warning",
"average": "Average",
"high": "High",
"disaster": "Disaster"
}
}
16 changes: 11 additions & 5 deletions src/utils/proxy/handlers/jsonrpc.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ import widgets from "widgets/widgets";

const logger = createLogger("jsonrpcProxyHandler");

export async function sendJsonRpcRequest(url, method, params, username, password) {
export async function sendJsonRpcRequest(url, method, params, widget) {
const headers = {
"content-type": "application/json",
accept: "application/json",
};

if (username && password) {
headers.authorization = `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`;
if (widget.username && widget.password) {
headers.Authorization = `Basic ${Buffer.from(`${widget.username}:${widget.password}`).toString("base64")}`;
}

if (widget.key) {
headers.Authorization = `Bearer ${widget.key}`;
}

const client = new JSONRPCClient(async (rpcRequest) => {
Expand Down Expand Up @@ -67,15 +71,17 @@ export default async function jsonrpcProxyHandler(req, res) {
const widget = await getServiceWidget(group, service);
const api = widgets?.[widget.type]?.api;

const [, mapping] = Object.entries(widgets?.[widget.type]?.mappings).find(([, value]) => value.endpoint === method);
const params = mapping?.params ?? null;

if (!api) {
return res.status(403).json({ error: "Service does not support API calls" });
}

if (widget) {
const url = formatApiCall(api, { ...widget });

// eslint-disable-next-line no-unused-vars
const [status, contentType, data] = await sendJsonRpcRequest(url, method, null, widget.username, widget.password);
const [status, , data] = await sendJsonRpcRequest(url, method, params, widget);
return res.status(status).end(data);
}
}
Expand Down
1 change: 1 addition & 0 deletions src/widgets/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ const components = {
wgeasy: dynamic(() => import("./wgeasy/component")),
whatsupdocker: dynamic(() => import("./whatsupdocker/component")),
xteve: dynamic(() => import("./xteve/component")),
zabbix: dynamic(() => import("./zabbix/component")),
};

export default components;
2 changes: 2 additions & 0 deletions src/widgets/widgets.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ import whatsupdocker from "./whatsupdocker/widget";
import xteve from "./xteve/widget";
import urbackup from "./urbackup/widget";
import romm from "./romm/widget";
import zabbix from "./zabbix/widget";

const widgets = {
adguard,
Expand Down Expand Up @@ -245,6 +246,7 @@ const widgets = {
wgeasy,
whatsupdocker,
xteve,
zabbix,
};

export default widgets;
46 changes: 46 additions & 0 deletions src/widgets/zabbix/component.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useTranslation } from "next-i18next";

import Container from "components/services/widget/container";
import Block from "components/services/widget/block";
import useWidgetAPI from "utils/proxy/use-widget-api";

const PriorityWarning = "2";
const PriorityAverage = "3";
const PriorityHigh = "4";
const PriorityDisaster = "5";

export default function Component({ service }) {
const { t } = useTranslation();
const { widget } = service;

const { data: zabbixData, error: zabbixError } = useWidgetAPI(widget, "trigger");

if (zabbixError) {
return <Container service={service} error={zabbixError} />;
}

if (!zabbixData) {
return (
<Container service={service}>
<Block label="zabbix.warning" />
<Block label="zabbix.average" />
<Block label="zabbix.high" />
<Block label="zabbix.disaster" />
</Container>
);
}

const warning = zabbixData.filter((item) => item.priority === PriorityWarning).length;
const average = zabbixData.filter((item) => item.priority === PriorityAverage).length;
const high = zabbixData.filter((item) => item.priority === PriorityHigh).length;
const disaster = zabbixData.filter((item) => item.priority === PriorityDisaster).length;

return (
<Container service={service}>
<Block label="zabbix.warning" value={t("common.number", { value: warning })} />
<Block label="zabbix.average" value={t("common.number", { value: average })} />
<Block label="zabbix.high" value={t("common.number", { value: high })} />
<Block label="zabbix.disaster" value={t("common.number", { value: disaster })} />
</Container>
);
}
23 changes: 23 additions & 0 deletions src/widgets/zabbix/widget.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import jsonrpcProxyHandler from "utils/proxy/handlers/jsonrpc";

const widget = {
api: "{url}/api_jsonrpc.php",
proxyHandler: jsonrpcProxyHandler,

mappings: {
trigger: {
endpoint: "trigger.get",
params: {
output: ["triggerid", "description", "priority"],
filter: {
value: 1,
},
sortfield: "priority",
sortorder: "DESC",
monitored: "true",
},
},
},
};

export default widget;

0 comments on commit 44f8e9d

Please sign in to comment.