feat: add template and template group management via GraphQL

- Implemented GraphQL endpoints for importing, querying, and deleting Zabbix templates and template groups. - Added support for full template data import, including items, preprocessing steps, tags, and linked templates. - Implemented dependent item support by deferred creation logic in the template importer. - Added ability to query templates and template groups with name pattern filtering (supporting Zabbix wildcards). - Implemented batch deletion for templates and template groups by ID or name pattern. - Improved error reporting by including detailed Zabbix API error data in GraphQL responses. - Added comprehensive unit and integration tests covering all new functionality. - Provided GraphQL sample queries and mutations in the 'docs' directory for all new endpoints.
This commit is contained in:
Andreas Hilbig 2026-01-24 15:42:13 +01:00
parent e641f8e610
commit a3ed4886a3
22 changed files with 2450 additions and 20 deletions

View file

@ -39,7 +39,7 @@ export class ParsedArgs {
constructor(params?: any) {
if (Array.isArray(params)) {
this.zabbix_params = params.map(arg => this.parseArgObject(arg))
} else if (params instanceof Object) {
} else {
this.zabbix_params = this.parseArgObject(params)
}
}
@ -52,9 +52,12 @@ export class ParsedArgs {
return paramName in this.zabbix_params ? this.zabbix_params[paramName] : undefined
}
parseArgObject(args?: Object) {
parseArgObject(args?: any) {
if (args && (typeof args !== 'object' || args.constructor !== Object)) {
return args;
}
let result: ZabbixParams
if (args) {
if (args && typeof args === 'object' && args.constructor === Object) {
if ("name_pattern" in args && typeof args["name_pattern"] == "string") {
if (args["name_pattern"]) {
this.name_pattern = args["name_pattern"]
@ -159,7 +162,10 @@ export class ZabbixRequest<T extends ZabbixResult, A extends ParsedArgs = Parsed
let params: ZabbixParams
if (Array.isArray(args?.zabbix_params)) {
params = args?.zabbix_params.map(paramsObj => {
return {...this.requestBodyTemplate.params, ...paramsObj}
if (paramsObj !== null && typeof paramsObj === 'object' && paramsObj.constructor === Object) {
return {...this.requestBodyTemplate.params, ...paramsObj}
}
return paramsObj;
})
} else {
params = {...this.requestBodyTemplate.params, ...zabbixParams ?? this.createZabbixParams(args)}

View file

@ -1,5 +1,7 @@
import { ZabbixRequest } from "./zabbix-request.js";
import {isZabbixErrorResult, ParsedArgs, ZabbixRequest} from "./zabbix-request.js";
import {ZabbixAPI} from "./zabbix-api.js";
import {logger} from "../logging/logger.js";
@ -30,3 +32,40 @@ export class ZabbixQueryTemplateGroupRequest extends ZabbixRequest<ZabbixQueryTe
}
export class ZabbixCreateTemplateGroupRequest extends ZabbixRequest<{ groupids: string[] }> {
constructor(authToken?: string | null, cookie?: string | null) {
super("templategroup.create", authToken, cookie);
}
}
export class ZabbixCreateTemplateRequest extends ZabbixRequest<{ templateids: string[] }> {
constructor(authToken?: string | null, cookie?: string | null) {
super("template.create", authToken, cookie);
}
}
export class ZabbixQueryItemRequest extends ZabbixRequest<any[]> {
constructor(authToken?: string | null, cookie?: string | null) {
super("item.get", authToken, cookie);
}
}
export class ZabbixCreateItemRequest extends ZabbixRequest<{ itemids: string[] }> {
constructor(authToken?: string | null, cookie?: string | null) {
super("item.create", authToken, cookie);
}
}
export class ZabbixDeleteTemplatesRequest extends ZabbixRequest<{ templateids: string[] }> {
constructor(authToken?: string | null, cookie?: string | null) {
super("template.delete", authToken, cookie);
}
}
export class ZabbixDeleteTemplateGroupsRequest extends ZabbixRequest<{ groupids: string[] }> {
constructor(authToken?: string | null, cookie?: string | null) {
super("templategroup.delete", authToken, cookie);
}
}