mirror of
				https://github.com/karl0ss/homepage.git
				synced 2025-10-31 06:24:02 +00:00 
			
		
		
		
	Feature: Zabbix service widget (#3905)
Co-Authored-By: shamoon <4887959+shamoon@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									4c6150a545
								
							
						
					
					
						commit
						44f8e9d4da
					
				| @ -79,7 +79,21 @@ By default the key is passed as an `X-API-Key` header. If you need to pass the k | |||||||
| 
 | 
 | ||||||
| ### `jsonrpcProxyHandler` | ### `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" | === "widget.js" | ||||||
| 
 | 
 | ||||||
| @ -93,6 +107,7 @@ A proxy handler that makes authenticated JSON-RPC requests to the specified API | |||||||
|       mappings: { |       mappings: { | ||||||
|         total: { endpoint: "total" }, |         total: { endpoint: "total" }, | ||||||
|         average: { endpoint: "average" }, |         average: { endpoint: "average" }, | ||||||
|  |         trigger: { endpoint: "trigger.get" }, | ||||||
|       }, |       }, | ||||||
|     }; |     }; | ||||||
|     ``` |     ``` | ||||||
| @ -110,6 +125,16 @@ A proxy handler that makes authenticated JSON-RPC requests to the specified API | |||||||
|           password: your-password |           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` | ### `synologyProxyHandler` | ||||||
| 
 | 
 | ||||||
| A proxy handler that makes authenticated requests to the specified Synology API endpoint. This is used exclusively for Synology DSM services. | A proxy handler that makes authenticated requests to the specified Synology API endpoint. This is used exclusively for Synology DSM services. | ||||||
|  | |||||||
| @ -128,3 +128,4 @@ You can also find a list of all available service widgets in the sidebar navigat | |||||||
| - [WGEasy](wgeasy.md) | - [WGEasy](wgeasy.md) | ||||||
| - [WhatsUpDocker](whatsupdocker.md) | - [WhatsUpDocker](whatsupdocker.md) | ||||||
| - [xTeVe](xteve.md) | - [xTeVe](xteve.md) | ||||||
|  | - [Zabbix](zabbix.md) | ||||||
|  | |||||||
							
								
								
									
										19
									
								
								docs/widgets/services/zabbix.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								docs/widgets/services/zabbix.md
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||||
|  | ``` | ||||||
| @ -152,6 +152,7 @@ nav: | |||||||
|           - widgets/services/wgeasy.md |           - widgets/services/wgeasy.md | ||||||
|           - widgets/services/whatsupdocker.md |           - widgets/services/whatsupdocker.md | ||||||
|           - widgets/services/xteve.md |           - widgets/services/xteve.md | ||||||
|  |           - widgets/services/zabbix.md | ||||||
|       - "Information Widgets": |       - "Information Widgets": | ||||||
|           - widgets/info/index.md |           - widgets/info/index.md | ||||||
|           - widgets/info/datetime.md |           - widgets/info/datetime.md | ||||||
|  | |||||||
| @ -931,5 +931,11 @@ | |||||||
|         "links": "Links", |         "links": "Links", | ||||||
|         "collections": "Collections", |         "collections": "Collections", | ||||||
|         "tags": "Tags" |         "tags": "Tags" | ||||||
|  |     }, | ||||||
|  |     "zabbix": { | ||||||
|  |       "warning": "Warning", | ||||||
|  |       "average": "Average", | ||||||
|  |       "high": "High", | ||||||
|  |       "disaster": "Disaster" | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -8,14 +8,18 @@ import widgets from "widgets/widgets"; | |||||||
| 
 | 
 | ||||||
| const logger = createLogger("jsonrpcProxyHandler"); | const logger = createLogger("jsonrpcProxyHandler"); | ||||||
| 
 | 
 | ||||||
| export async function sendJsonRpcRequest(url, method, params, username, password) { | export async function sendJsonRpcRequest(url, method, params, widget) { | ||||||
|   const headers = { |   const headers = { | ||||||
|     "content-type": "application/json", |     "content-type": "application/json", | ||||||
|     accept: "application/json", |     accept: "application/json", | ||||||
|   }; |   }; | ||||||
| 
 | 
 | ||||||
|   if (username && password) { |   if (widget.username && widget.password) { | ||||||
|     headers.authorization = `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`; |     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) => { |   const client = new JSONRPCClient(async (rpcRequest) => { | ||||||
| @ -67,6 +71,9 @@ export default async function jsonrpcProxyHandler(req, res) { | |||||||
|     const widget = await getServiceWidget(group, service); |     const widget = await getServiceWidget(group, service); | ||||||
|     const api = widgets?.[widget.type]?.api; |     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) { |     if (!api) { | ||||||
|       return res.status(403).json({ error: "Service does not support API calls" }); |       return res.status(403).json({ error: "Service does not support API calls" }); | ||||||
|     } |     } | ||||||
| @ -74,8 +81,7 @@ export default async function jsonrpcProxyHandler(req, res) { | |||||||
|     if (widget) { |     if (widget) { | ||||||
|       const url = formatApiCall(api, { ...widget }); |       const url = formatApiCall(api, { ...widget }); | ||||||
| 
 | 
 | ||||||
|       // eslint-disable-next-line no-unused-vars
 |       const [status, , data] = await sendJsonRpcRequest(url, method, params, widget); | ||||||
|       const [status, contentType, data] = await sendJsonRpcRequest(url, method, null, widget.username, widget.password); |  | ||||||
|       return res.status(status).end(data); |       return res.status(status).end(data); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  | |||||||
| @ -127,6 +127,7 @@ const components = { | |||||||
|   wgeasy: dynamic(() => import("./wgeasy/component")), |   wgeasy: dynamic(() => import("./wgeasy/component")), | ||||||
|   whatsupdocker: dynamic(() => import("./whatsupdocker/component")), |   whatsupdocker: dynamic(() => import("./whatsupdocker/component")), | ||||||
|   xteve: dynamic(() => import("./xteve/component")), |   xteve: dynamic(() => import("./xteve/component")), | ||||||
|  |   zabbix: dynamic(() => import("./zabbix/component")), | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export default components; | export default components; | ||||||
|  | |||||||
| @ -119,6 +119,7 @@ import whatsupdocker from "./whatsupdocker/widget"; | |||||||
| import xteve from "./xteve/widget"; | import xteve from "./xteve/widget"; | ||||||
| import urbackup from "./urbackup/widget"; | import urbackup from "./urbackup/widget"; | ||||||
| import romm from "./romm/widget"; | import romm from "./romm/widget"; | ||||||
|  | import zabbix from "./zabbix/widget"; | ||||||
| 
 | 
 | ||||||
| const widgets = { | const widgets = { | ||||||
|   adguard, |   adguard, | ||||||
| @ -245,6 +246,7 @@ const widgets = { | |||||||
|   wgeasy, |   wgeasy, | ||||||
|   whatsupdocker, |   whatsupdocker, | ||||||
|   xteve, |   xteve, | ||||||
|  |   zabbix, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export default widgets; | export default widgets; | ||||||
|  | |||||||
							
								
								
									
										46
									
								
								src/widgets/zabbix/component.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/widgets/zabbix/component.jsx
									
									
									
									
									
										Normal file
									
								
							| @ -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
									
								
								src/widgets/zabbix/widget.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/widgets/zabbix/widget.js
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Mitchell
						Mitchell