Skip to content

Commit b0a7b3f

Browse files
authored
Merge pull request claranet#15 from claranet/zabbix54
Add Zabbix 5.4+ compatibility
2 parents 1651899 + 7531972 commit b0a7b3f

15 files changed

+391
-36
lines changed

.github/workflows/test-zabbix.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ jobs:
1111
strategy:
1212
fail-fast: false
1313
matrix:
14-
zabbix_version: ["3.0", "3.2", "3.4", "4.0", "4.2", "4.4", "5.0", "5.2"]
14+
zabbix_version: ["3.0", "3.2", "3.4", "4.0", "4.2", "4.4", "5.0", "5.2", "5.4", "6.0", "6.2"]
1515

1616
services:
1717
mysql-server:

application_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ func testDeleteApplication(app *zapi.Application, t *testing.T) {
2626
}
2727

2828
func TestApplications(t *testing.T) {
29+
skipTestIfVersionGreaterThanOrEqual(t, "5.4", "dropped support for Application API")
30+
2931
api := testGetAPI(t)
3032

3133
group := testCreateHostGroup(t)

base_test.go

+34
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"time"
1111

1212
zapi "github.com/claranet/go-zabbix-api"
13+
"github.com/hashicorp/go-version"
1314
)
1415

1516
var (
@@ -62,6 +63,39 @@ func testGetAPI(t *testing.T) *zapi.API {
6263
return _api
6364
}
6465

66+
func compVersion(t *testing.T, comparedVersion string) (int, string) {
67+
api := testGetAPI(t)
68+
serverVersion, err := api.Version()
69+
if err != nil {
70+
t.Fatal(err)
71+
}
72+
sVersion, _ := version.NewVersion(serverVersion)
73+
cVersion, _ := version.NewVersion(comparedVersion)
74+
return sVersion.Compare(cVersion), serverVersion
75+
}
76+
77+
func isVersionLessThan(t *testing.T, comparedVersion string) (bool, string) {
78+
comp, serverVersion := compVersion(t, comparedVersion)
79+
return comp < 0, serverVersion
80+
}
81+
82+
func isVersionGreaterThanOrEqual(t *testing.T, comparedVersion string) (bool, string) {
83+
comp, serverVersion := compVersion(t, comparedVersion)
84+
return comp >= 0, serverVersion
85+
}
86+
87+
func skipTestIfVersionGreaterThanOrEqual(t *testing.T, comparedVersion, msg string) {
88+
if compGreaterThanOrEqual, serverVersion := isVersionGreaterThanOrEqual(t, comparedVersion); compGreaterThanOrEqual {
89+
t.Skipf("Zabbix version %s is greater than or equal to %s which %s, skipping test.", serverVersion, comparedVersion, msg)
90+
}
91+
}
92+
93+
func skipTestIfVersionLessThan(t *testing.T, comparedVersion, msg string) {
94+
if compGreaterThanOrEqual, serverVersion := isVersionLessThan(t, comparedVersion); compGreaterThanOrEqual {
95+
t.Skipf("Zabbix version %s is less than to %s which %s, skipping test.", serverVersion, comparedVersion, msg)
96+
}
97+
}
98+
6599
func TestBadCalls(t *testing.T) {
66100
api := testGetAPI(t)
67101
res, err := api.Call("", nil)

go.mod

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
module github.com/claranet/go-zabbix-api
22

33
go 1.18
4+
5+
require github.com/hashicorp/go-version v1.6.0 // indirect

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
2+
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=

host.go

+7-8
Original file line numberDiff line numberDiff line change
@@ -145,16 +145,15 @@ func (api *API) HostsDelete(hosts Hosts) (err error) {
145145
// HostsDeleteByIds Wrapper for host.delete
146146
// https://www.zabbix.com/documentation/3.2/manual/api/reference/host/delete
147147
func (api *API) HostsDeleteByIds(ids []string) (err error) {
148-
hostIds := make([]map[string]string, len(ids))
149-
for i, id := range ids {
150-
hostIds[i] = map[string]string{"hostid": id}
151-
}
152-
153-
response, err := api.CallWithError("host.delete", hostIds)
148+
response, err := api.CallWithError("host.delete", ids)
154149
if err != nil {
155-
// Zabbix 2.4 uses new syntax only
156150
if e, ok := err.(*Error); ok && e.Code == -32500 {
157-
response, err = api.CallWithError("host.delete", ids)
151+
// Zabbix 2.0 and older use old syntax only with hostid
152+
hostIds := make([]map[string]string, len(ids))
153+
for i, id := range ids {
154+
hostIds[i] = map[string]string{"hostid": id}
155+
}
156+
response, err = api.CallWithError("host.delete", hostIds)
158157
}
159158
}
160159
if err != nil {

item_prototype_test.go

+21-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"testing"
55

66
dd "github.com/claranet/go-zabbix-api"
7+
zapi "github.com/claranet/go-zabbix-api"
78
)
89

910
func testCreateItemPrototype(template *dd.Template, lldRule *dd.LLDRule, t *testing.T) *dd.ItemPrototype {
@@ -34,10 +35,27 @@ func testDeleteItemPrototype(item *dd.ItemPrototype, t *testing.T) {
3435
func testItemPrototype(t *testing.T) {
3536
api := testGetAPI(t)
3637

37-
hostGroup := testCreateHostGroup(t)
38-
defer testDeleteHostGroup(hostGroup, t)
38+
// Zabbix v6.2 introduced Template Groups and requires them for Templates
39+
var groupIds zapi.HostGroupIDs
40+
if compLessThan, _ := isVersionLessThan(t, "6.2"); compLessThan {
41+
hostGroup := testCreateHostGroup(t)
42+
defer testDeleteHostGroup(hostGroup, t)
43+
groupIds = zapi.HostGroupIDs{
44+
{
45+
GroupID: hostGroup.GroupID,
46+
},
47+
}
48+
} else {
49+
templateGroup := testCreateTemplateGroup(t)
50+
defer testDeleteTemplateGroup(templateGroup, t)
51+
groupIds = zapi.HostGroupIDs{
52+
{
53+
GroupID: templateGroup.GroupID,
54+
},
55+
}
56+
}
3957

40-
template := testCreateTemplate(hostGroup, t)
58+
template := testCreateTemplate(&groupIds, t)
4159
defer testDeleteTemplate(template, t)
4260

4361
lldRule := testCreateLLDRule(template, t)

item_test.go

+44-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,22 @@ import (
66
zapi "github.com/claranet/go-zabbix-api"
77
)
88

9-
func testCreateItem(app *zapi.Application, t *testing.T) *zapi.Item {
9+
func testCreateItem(host *zapi.Host, t *testing.T) *zapi.Item {
10+
items := zapi.Items{{
11+
HostID: host.HostID,
12+
Key: "key.lala.laa",
13+
Name: "name for key",
14+
Type: zapi.ZabbixTrapper,
15+
Delay: "0",
16+
}}
17+
err := testGetAPI(t).ItemsCreate(items)
18+
if err != nil {
19+
t.Fatal(err)
20+
}
21+
return &items[0]
22+
}
23+
24+
func testCreateItemWithApplication(app *zapi.Application, t *testing.T) *zapi.Item {
1025
items := zapi.Items{{
1126
HostID: app.HostID,
1227
Key: "key.lala.laa",
@@ -38,6 +53,33 @@ func TestItems(t *testing.T) {
3853
host := testCreateHost(group, t)
3954
defer testDeleteHost(host, t)
4055

56+
item := testCreateItem(host, t)
57+
58+
_, err := api.ItemGetByID(item.ItemID)
59+
if err != nil {
60+
t.Fatal(err)
61+
}
62+
63+
item.Name = "another name"
64+
err = api.ItemsUpdate(zapi.Items{*item})
65+
if err != nil {
66+
t.Error(err)
67+
}
68+
69+
testDeleteItem(item, t)
70+
}
71+
72+
func TestItemsWithApplication(t *testing.T) {
73+
skipTestIfVersionGreaterThanOrEqual(t, "5.4", "dropped support for Application API")
74+
75+
api := testGetAPI(t)
76+
77+
group := testCreateHostGroup(t)
78+
defer testDeleteHostGroup(group, t)
79+
80+
host := testCreateHost(group, t)
81+
defer testDeleteHost(host, t)
82+
4183
app := testCreateApplication(host, t)
4284
defer testDeleteApplication(app, t)
4385

@@ -49,7 +91,7 @@ func TestItems(t *testing.T) {
4991
t.Fatal("Found items")
5092
}
5193

52-
item := testCreateItem(app, t)
94+
item := testCreateItemWithApplication(app, t)
5395

5496
_, err = api.ItemGetByID(item.ItemID)
5597
if err != nil {

lld_rule_test.go

+21-3
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"testing"
55

66
dd "github.com/claranet/go-zabbix-api"
7+
zapi "github.com/claranet/go-zabbix-api"
78
)
89

910
func testCreateLLDRule(template *dd.Template, t *testing.T) *dd.LLDRule {
@@ -42,10 +43,27 @@ func testDeleteLLDRule(rule *dd.LLDRule, t *testing.T) {
4243
func TestLLDRule(t *testing.T) {
4344
api := testGetAPI(t)
4445

45-
hostGroup := testCreateHostGroup(t)
46-
defer testDeleteHostGroup(hostGroup, t)
46+
// Zabbix v6.2 introduced Template Groups and requires them for Templates
47+
var groupIds zapi.HostGroupIDs
48+
if compLessThan, _ := isVersionLessThan(t, "6.2"); compLessThan {
49+
hostGroup := testCreateHostGroup(t)
50+
defer testDeleteHostGroup(hostGroup, t)
51+
groupIds = zapi.HostGroupIDs{
52+
{
53+
GroupID: hostGroup.GroupID,
54+
},
55+
}
56+
} else {
57+
templateGroup := testCreateTemplateGroup(t)
58+
defer testDeleteTemplateGroup(templateGroup, t)
59+
groupIds = zapi.HostGroupIDs{
60+
{
61+
GroupID: templateGroup.GroupID,
62+
},
63+
}
64+
}
4765

48-
template := testCreateTemplate(hostGroup, t)
66+
template := testCreateTemplate(&groupIds, t)
4967
defer testDeleteTemplate(template, t)
5068

5169
lldRule := testCreateLLDRule(template, t)

template.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ package zabbix
33
// Template represent Zabbix Template type returned from Zabbix API
44
// https://www.zabbix.com/documentation/3.2/manual/api/reference/template/object
55
type Template struct {
6-
TemplateID string `json:"templateid,omitempty"`
7-
Host string `json:"host"`
8-
Description string `json:"description,omitempty"`
9-
Name string `json:"name,omitempty"`
10-
Groups HostGroups `json:"groups"`
11-
UserMacros Macros `json:"macros"`
12-
LinkedTemplates Templates `json:"templates,omitempty"`
13-
TemplatesClear Templates `json:"templates_clear,omitempty"`
14-
LinkedHosts Hosts `json:"hosts,omitempty"`
6+
TemplateID string `json:"templateid,omitempty"`
7+
Host string `json:"host"`
8+
Description string `json:"description,omitempty"`
9+
Name string `json:"name,omitempty"`
10+
Groups HostGroupIDs `json:"groups"`
11+
UserMacros Macros `json:"macros,omitempty"`
12+
LinkedTemplates Templates `json:"templates,omitempty"`
13+
TemplatesClear Templates `json:"templates_clear,omitempty"`
14+
LinkedHosts Hosts `json:"hosts,omitempty"`
1515
}
1616

1717
// Templates is an Array of Template structs.

template_group.go

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package zabbix
2+
3+
// TemplateGroup represent Zabbix template group object, new in v6.2
4+
// https://www.zabbix.com/documentation/6.2/en/manual/api/reference/templategroup/object
5+
type TemplateGroup struct {
6+
GroupID string `json:"groupid,omitempty"`
7+
Name string `json:"name"`
8+
}
9+
10+
// TemplateGroups is an array of TemplateGroup
11+
type TemplateGroups []TemplateGroup
12+
13+
// TemplateGroupsGet Wrapper for templategroup.get
14+
// https://www.zabbix.com/documentation/6.2/en/manual/api/reference/templategroup/get
15+
func (api *API) TemplateGroupsGet(params Params) (res TemplateGroups, err error) {
16+
if _, present := params["output"]; !present {
17+
params["output"] = "extend"
18+
}
19+
err = api.CallWithErrorParse("templategroup.get", params, &res)
20+
return
21+
}
22+
23+
// TemplateGroupGetByID Gets host group by Id only if there is exactly 1 matching host group.
24+
// https://www.zabbix.com/documentation/6.2/en/manual/api/reference/templategroup/get
25+
func (api *API) TemplateGroupGetByID(id string) (res *TemplateGroup, err error) {
26+
groups, err := api.TemplateGroupsGet(Params{"groupids": id})
27+
if err != nil {
28+
return
29+
}
30+
31+
if len(groups) == 1 {
32+
res = &groups[0]
33+
} else {
34+
e := ExpectedOneResult(len(groups))
35+
err = &e
36+
}
37+
return
38+
}
39+
40+
// TemplateGroupsCreate Wrapper for templategroup.create
41+
// https://www.zabbix.com/documentation/6.2/en/manual/api/reference/templategroup/create
42+
func (api *API) TemplateGroupsCreate(TemplateGroups TemplateGroups) (err error) {
43+
response, err := api.CallWithError("templategroup.create", TemplateGroups)
44+
if err != nil {
45+
return
46+
}
47+
48+
result := response.Result.(map[string]interface{})
49+
groupids := result["groupids"].([]interface{})
50+
for i, id := range groupids {
51+
TemplateGroups[i].GroupID = id.(string)
52+
}
53+
return
54+
}
55+
56+
// TemplateGroupsUpdate Wrapper for templategroup.update
57+
// https://www.zabbix.com/documentation/6.2/en/manual/api/reference/templategroup/update
58+
func (api *API) TemplateGroupsUpdate(TemplateGroups TemplateGroups) (err error) {
59+
_, err = api.CallWithError("templategroup.update", TemplateGroups)
60+
return
61+
}
62+
63+
// TemplateGroupsDelete Wrapper for templategroup.delete
64+
// Cleans GroupId in all TemplateGroups elements if call succeed.
65+
// https://www.zabbix.com/documentation/6.2/en/manual/api/reference/templategroup/delete
66+
func (api *API) TemplateGroupsDelete(TemplateGroups TemplateGroups) (err error) {
67+
ids := make([]string, len(TemplateGroups))
68+
for i, group := range TemplateGroups {
69+
ids[i] = group.GroupID
70+
}
71+
72+
err = api.TemplateGroupsDeleteByIds(ids)
73+
if err == nil {
74+
for i := range TemplateGroups {
75+
TemplateGroups[i].GroupID = ""
76+
}
77+
}
78+
return
79+
}
80+
81+
// TemplateGroupsDeleteByIds Wrapper for templategroup.delete
82+
// https://www.zabbix.com/documentation/6.2/en/manual/api/reference/templategroup/delete
83+
func (api *API) TemplateGroupsDeleteByIds(ids []string) (err error) {
84+
response, err := api.CallWithError("templategroup.delete", ids)
85+
if err != nil {
86+
return
87+
}
88+
89+
result := response.Result.(map[string]interface{})
90+
groupids := result["groupids"].([]interface{})
91+
if len(ids) != len(groupids) {
92+
err = &ExpectedMore{len(ids), len(groupids)}
93+
}
94+
return
95+
}

0 commit comments

Comments
 (0)