From 8d16f21247eb48a5108d3b6dc33c0b2efeb20785 Mon Sep 17 00:00:00 2001 From: Michael Freeman Date: Thu, 31 Aug 2023 13:18:03 -0500 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=9A=A7=20WIP=20adding=20support=20for?= =?UTF-8?q?=20problem=20get?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/modules.xml | 8 +++++ .idea/nxs-go-zabbix.iml | 9 ++++++ problem.go | 68 +++++++++++++++++++++++++++++++++++++++++ problem_test.go | 36 ++++++++++++++++++++++ 4 files changed, 121 insertions(+) create mode 100644 .idea/modules.xml create mode 100644 .idea/nxs-go-zabbix.iml create mode 100644 problem.go create mode 100644 problem_test.go diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..72d1e4a --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/nxs-go-zabbix.iml b/.idea/nxs-go-zabbix.iml new file mode 100644 index 0000000..5e764c4 --- /dev/null +++ b/.idea/nxs-go-zabbix.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/problem.go b/problem.go new file mode 100644 index 0000000..59278dc --- /dev/null +++ b/problem.go @@ -0,0 +1,68 @@ +package zabbix + +type ZabbixProblemObject struct { + EventID string `json:"eventid,omitempty"` + Source string `json:"source,omitempty"` + Object string `json:"object,omitempty"` + ObjectID string `json:"objectid,omitempty"` + Clock string `json:"clock,omitempty"` + Ns string `json:"ns,omitempty"` + REventID string `json:"r_eventid,omitempty"` + RClock string `json:"r_clock,omitempty"` + RNs string `json:"r_ns,omitempty"` + CorrelationID string `json:"correlationid,omitempty"` + UserID string `json:"userid,omitempty"` + Name string `json:"name,omitempty"` + Acknowledged string `json:"acknowledged,omitempty"` + Severity string `json:"severity,omitempty"` + CauseEventID string `json:"cause_eventid,omitempty"` + OpData string `json:"opdata,omitempty"` + Acknowledges []ZabbixAcknowledge `json:"acknowledges,omitempty"` + Suppression []ZabbixSuppression `json:"suppression_data,omitempty"` + Suppressed string `json:"suppressed,omitempty"` + Tags []ZabbixProblemTag `json:"tags,omitempty"` +} + +type ZabbixAcknowledge struct { + AcknowledgeID string `json:"acknowledgeid,omitempty"` + UserID string `json:"userid,omitempty"` + EventID string `json:"eventid,omitempty"` + Clock string `json:"clock,omitempty"` + Message string `json:"message,omitempty"` + Action string `json:"action,omitempty"` + OldSeverity string `json:"old_severity,omitempty"` + NewSeverity string `json:"new_severity,omitempty"` + SuppressUntil string `json:"suppress_until,omitempty"` + TaskID string `json:"taskid,omitempty"` +} + +type ZabbixSuppression struct { + MaintenanceID string `json:"maintenanceid,omitempty"` + SuppressUntil string `json:"suppress_until,omitempty"` + UserID string `json:"userid,omitempty"` +} + +type ZabbixProblemTag struct { + Tag string `json:"tag,omitempty"` + Value string `json:"value,omitempty"` +} + +// ProblemGetParams struct is used for problem get requests +type ProblemGetParams struct { + GetParameters + + ObjectIDs []string `json:"objectids,omitempty"` + // ... Add other fields as needed +} + +// ProblemGet gets problems +func (z *Context) ProblemGet(params ProblemGetParams) ([]ZabbixProblemObject, int, error) { + var result []ZabbixProblemObject + + status, err := z.request("problem.get", params, &result) + if err != nil { + return nil, status, err + } + + return result, status, nil +} diff --git a/problem_test.go b/problem_test.go new file mode 100644 index 0000000..7f463ab --- /dev/null +++ b/problem_test.go @@ -0,0 +1,36 @@ +package zabbix + +import ( + "fmt" + "os" + "testing" +) + +func TestProblemGet(t *testing.T) { + z := &Context{} + err := z.Login(os.Getenv("ZABBIX_HOST"), os.Getenv("ZABBIX_USERNAME"), os.Getenv("ZABBIX_PASSWORD")) + if err != nil { + t.Fatalf("Login failed: %s", err) + } + + params := ProblemGetParams{ + ObjectIDs: []string{"20143"}, + // ... Add other fields as needed + } + + problems, _, err := z.ProblemGet(params) + if err != nil { + t.Fatalf("ProblemGet failed: %s", err) + } + + if len(problems) == 0 { + t.Fatalf("No problems found") + } + + fmt.Println("Problems list:") + for _, p := range problems { + fmt.Println(p) + } + + // ... Add more tests to validate the results +} From f728a8fd9e7e3c97674668ee4e2b174ce52f1539 Mon Sep 17 00:00:00 2001 From: Michael Freeman Date: Thu, 31 Aug 2023 13:19:49 -0500 Subject: [PATCH 2/5] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20updated=20deps=20and?= =?UTF-8?q?=20go=20version=20to=201.20?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 4 ++-- go.sum | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 778278d..584136d 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/nixys/nxs-go-zabbix/v5 -go 1.14 +go 1.20 -require github.com/mitchellh/mapstructure v1.3.0 +require github.com/mitchellh/mapstructure v1.5.0 diff --git a/go.sum b/go.sum index 43df515..35c0981 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,4 @@ github.com/mitchellh/mapstructure v1.3.0 h1:iDwIio/3gk2QtLLEsqU5lInaMzos0hDTz8a6lazSFVw= github.com/mitchellh/mapstructure v1.3.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= From fedd15f670f92a8057d777fe14ea60ea4d211cbc Mon Sep 17 00:00:00 2001 From: Michael Freeman Date: Thu, 31 Aug 2023 13:20:25 -0500 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=99=88=20updating=20gitignore?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index d1542d4..53fa8a0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ -/.project -/.vscode +.project +.vscode +.idea +.env From 494cd4d5c48e7784b7559c920ab41223b3a79afb Mon Sep 17 00:00:00 2001 From: Michael Freeman Date: Thu, 31 Aug 2023 20:19:39 -0500 Subject: [PATCH 4/5] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20removing=20.idea=20cra?= =?UTF-8?q?p?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/modules.xml | 8 -------- .idea/nxs-go-zabbix.iml | 9 --------- README.md | 7 +++++++ 3 files changed, 7 insertions(+), 17 deletions(-) delete mode 100644 .idea/modules.xml delete mode 100644 .idea/nxs-go-zabbix.iml diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 72d1e4a..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/nxs-go-zabbix.iml b/.idea/nxs-go-zabbix.iml deleted file mode 100644 index 5e764c4..0000000 --- a/.idea/nxs-go-zabbix.iml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index 7e9a000..718da4e 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,13 @@ Run: ZABBIX_HOST="https://zabbix.yourdomain.com/api_jsonrpc.php" ZABBIX_USERNAME="Admin" ZABBIX_PASSWORD="PASSWORD" go run main.go ``` +Test: + +``` +ZABBIX_HOST="https://zabbix.yourdomain.com/api_jsonrpc.php" ZABBIX_USERNAME="Admin" ZABBIX_PASSWORD="PASSWORD" go test -v -run TestProblemGet +``` + + ## Feedback For support and feedback please contact me: From 1580bd20bba3ce6a540919422708d38a42247638 Mon Sep 17 00:00:00 2001 From: Boris Ershov Date: Tue, 19 Sep 2023 13:05:23 +0700 Subject: [PATCH 5/5] feat(PR #7): Add API method for `Problem` --- event.go | 15 +++++ history_test.go | 2 +- problem.go | 162 ++++++++++++++++++++++++++++++++++++------------ problem_test.go | 47 +++++++------- zabbix.go | 4 +- 5 files changed, 162 insertions(+), 68 deletions(-) create mode 100644 event.go diff --git a/event.go b/event.go new file mode 100644 index 0000000..9a9863e --- /dev/null +++ b/event.go @@ -0,0 +1,15 @@ +package zabbix + +type EventAcknowledgeActionType int64 + +const ( + EventAcknowledgeActionTypeClose EventAcknowledgeActionType = 1 + EventAcknowledgeActionTypeAck EventAcknowledgeActionType = 2 + EventAcknowledgeActionTypeAddMessage EventAcknowledgeActionType = 4 + EventAcknowledgeActionTypeChangeSeverity EventAcknowledgeActionType = 8 + EventAcknowledgeActionTypeUnack EventAcknowledgeActionType = 16 + EventAcknowledgeActionTypeSuppress EventAcknowledgeActionType = 32 + EventAcknowledgeActionTypeUnsuppress EventAcknowledgeActionType = 64 + EventAcknowledgeActionTypeChangeEventRankCause EventAcknowledgeActionType = 128 + EventAcknowledgeActionTypeChangeEventRankSymptom EventAcknowledgeActionType = 256 +) diff --git a/history_test.go b/history_test.go index 2fd47ef..c85cf66 100644 --- a/history_test.go +++ b/history_test.go @@ -27,7 +27,7 @@ func testHistoryGet(t *testing.T, z Context) []HistoryFloatObject { hObjects, _, err := z.HistoryGet(HistoryGetParams{ History: HistoryObjectTypeFloat, - ItemIDs: []int{testHistoryItemID}, + //ItemIDs: []int{testHistoryItemID}, GetParameters: GetParameters{ Limit: 1, }, diff --git a/problem.go b/problem.go index 59278dc..f429df5 100644 --- a/problem.go +++ b/problem.go @@ -1,63 +1,143 @@ package zabbix -type ZabbixProblemObject struct { - EventID string `json:"eventid,omitempty"` - Source string `json:"source,omitempty"` - Object string `json:"object,omitempty"` - ObjectID string `json:"objectid,omitempty"` - Clock string `json:"clock,omitempty"` - Ns string `json:"ns,omitempty"` - REventID string `json:"r_eventid,omitempty"` - RClock string `json:"r_clock,omitempty"` - RNs string `json:"r_ns,omitempty"` - CorrelationID string `json:"correlationid,omitempty"` - UserID string `json:"userid,omitempty"` - Name string `json:"name,omitempty"` - Acknowledged string `json:"acknowledged,omitempty"` - Severity string `json:"severity,omitempty"` - CauseEventID string `json:"cause_eventid,omitempty"` - OpData string `json:"opdata,omitempty"` - Acknowledges []ZabbixAcknowledge `json:"acknowledges,omitempty"` - Suppression []ZabbixSuppression `json:"suppression_data,omitempty"` - Suppressed string `json:"suppressed,omitempty"` - Tags []ZabbixProblemTag `json:"tags,omitempty"` +type ProblemSourceType int64 + +const ( + ProblemSourceTypeTrigger ProblemSourceType = 0 + ProblemSourceTypeInternal ProblemSourceType = 3 + ProblemSourceTypeServiceStatusUpdate ProblemSourceType = 4 +) + +type ProblemObjectType int64 + +const ( + ProblemObjectTypeTrigger ProblemObjectType = 0 + ProblemObjectTypeItem ProblemObjectType = 4 + ProblemObjectTypeLLDRule ProblemObjectType = 5 + ProblemObjectTypeService ProblemObjectType = 6 +) + +type ProblemAcknowledgeType int64 + +const ( + ProblemAcknowledgeTypeFalse ProblemAcknowledgeType = 0 + ProblemAcknowledgeTypeTrue ProblemAcknowledgeType = 1 +) + +type ProblemSeverityType int64 + +const ( + ProblemSeverityTypeNotClassified ProblemSeverityType = 0 + ProblemSeverityTypeInformation ProblemSeverityType = 1 + ProblemSeverityTypeWarning ProblemSeverityType = 2 + ProblemSeverityTypeAverage ProblemSeverityType = 3 + ProblemSeverityTypeHigh ProblemSeverityType = 4 + ProblemSeverityTypeDisaster ProblemSeverityType = 5 +) + +type ProblemSuppressedType int64 + +const ( + ProblemSuppressedTypeNormalState ProblemSuppressedType = 0 + ProblemSuppressedTypeSuppressed ProblemSuppressedType = 1 +) + +type ProblemEvalType int64 + +const ( + ProblemEvalTypeAndOr ProblemEvalType = 0 + ProblemEvalTypeOR ProblemEvalType = 2 +) + +// ProblemObject struct is used to store problem operations results +// +// see: https://www.zabbix.com/documentation/5.0/en/manual/api/reference/problem/object +type ProblemObject struct { + EventID int64 `json:"eventid,omitempty"` + Source ProblemSourceType `json:"source,omitempty"` + Object ProblemObjectType `json:"object,omitempty"` + ObjectID int64 `json:"objectid,omitempty"` + Clock int64 `json:"clock,omitempty"` + Ns int64 `json:"ns,omitempty"` + REventID int64 `json:"r_eventid,omitempty"` + RClock int64 `json:"r_clock,omitempty"` + RNs int64 `json:"r_ns,omitempty"` + CauseEventID int64 `json:"cause_eventid,omitempty"` + CorrelationID int64 `json:"correlationid,omitempty"` + UserID int64 `json:"userid,omitempty"` + Name string `json:"name,omitempty"` + Acknowledged ProblemAcknowledgeType `json:"acknowledged,omitempty"` + Severity ProblemSeverityType `json:"severity,omitempty"` + Suppressed ProblemSuppressedType `json:"suppressed,omitempty"` + OpData string `json:"opdata,omitempty"` + URLs []ProblemMediaTypeURLObject `json:"urls,omitempty"` + Acknowledges []ProblemAcknowledgeObject `json:"acknowledges,omitempty"` + Tags []ProblemTagObject `json:"tags,omitempty"` + Suppression []ProblemSuppressionObject `json:"suppression_data,omitempty"` } -type ZabbixAcknowledge struct { - AcknowledgeID string `json:"acknowledgeid,omitempty"` - UserID string `json:"userid,omitempty"` - EventID string `json:"eventid,omitempty"` - Clock string `json:"clock,omitempty"` - Message string `json:"message,omitempty"` - Action string `json:"action,omitempty"` - OldSeverity string `json:"old_severity,omitempty"` - NewSeverity string `json:"new_severity,omitempty"` - SuppressUntil string `json:"suppress_until,omitempty"` - TaskID string `json:"taskid,omitempty"` +type ProblemAcknowledgeObject struct { + AcknowledgeID int64 `json:"acknowledgeid,omitempty"` + UserID int64 `json:"userid,omitempty"` + EventID int64 `json:"eventid,omitempty"` + Clock int64 `json:"clock,omitempty"` + Message string `json:"message,omitempty"` + Action EventAcknowledgeActionType `json:"action,omitempty"` + OldSeverity ProblemSeverityType `json:"old_severity,omitempty"` + NewSeverity ProblemSeverityType `json:"new_severity,omitempty"` + SuppressUntil int64 `json:"suppress_until,omitempty"` + TaskID int64 `json:"taskid,omitempty"` } -type ZabbixSuppression struct { - MaintenanceID string `json:"maintenanceid,omitempty"` - SuppressUntil string `json:"suppress_until,omitempty"` - UserID string `json:"userid,omitempty"` +type ProblemMediaTypeURLObject struct { + Name string `json:"name,omitempty"` + URL string `json:"url,omitempty"` } -type ZabbixProblemTag struct { +type ProblemTagObject struct { Tag string `json:"tag,omitempty"` Value string `json:"value,omitempty"` } +type ProblemSuppressionObject struct { + MaintenanceID int64 `json:"maintenanceid,omitempty"` + UserID int64 `json:"userid,omitempty"` + SuppressUntil int64 `json:"suppress_until,omitempty"` +} + // ProblemGetParams struct is used for problem get requests +// +// see: https://www.zabbix.com/documentation/5.0/en/manual/api/reference/problem/get#parameters type ProblemGetParams struct { GetParameters - ObjectIDs []string `json:"objectids,omitempty"` - // ... Add other fields as needed + EventIDs []int64 `json:"eventids,omitempty"` + GroupIDs []int64 `json:"groupids,omitempty"` + HostIDs []int64 `json:"hostids,omitempty"` + ObjectIDs []int64 `json:"objectids,omitempty"` + ApplicationIDs []int64 `json:"applicationids,omitempty"` + Source ProblemSourceType `json:"source,omitempty"` + Object ProblemObjectType `json:"object,omitempty"` + Acknowledged bool `json:"acknowledged,omitempty"` + Suppressed bool `json:"suppressed,omitempty"` + Severities []ProblemSeverityType `json:"severities,omitempty"` + Evaltype ProblemEvalType `json:"evaltype,omitempty"` + Tags []ProblemTagObject `json:"tags,omitempty"` + Recent bool `json:"recent,omitempty"` + EventIDFrom int64 `json:"eventid_from,omitempty"` + EventIDTill int64 `json:"eventid_till,omitempty"` + TimeFrom int64 `json:"time_from,omitempty"` + TimeTill int64 `json:"time_till,omitempty"` + SelectAcknowledges SelectQuery `json:"selectAcknowledges,omitempty"` + SelectTags SelectQuery `json:"selectTags,omitempty"` + SelectSuppressionData SelectQuery `json:"selectSuppressionData,omitempty"` + SortField []string `json:"sortfield,omitempty"` } // ProblemGet gets problems -func (z *Context) ProblemGet(params ProblemGetParams) ([]ZabbixProblemObject, int, error) { - var result []ZabbixProblemObject +func (z *Context) ProblemGet(params ProblemGetParams) ([]ProblemObject, int, error) { + + var result []ProblemObject status, err := z.request("problem.get", params, &result) if err != nil { diff --git a/problem_test.go b/problem_test.go index 7f463ab..5251649 100644 --- a/problem_test.go +++ b/problem_test.go @@ -1,36 +1,35 @@ package zabbix import ( - "fmt" - "os" "testing" ) -func TestProblemGet(t *testing.T) { - z := &Context{} - err := z.Login(os.Getenv("ZABBIX_HOST"), os.Getenv("ZABBIX_USERNAME"), os.Getenv("ZABBIX_PASSWORD")) - if err != nil { - t.Fatalf("Login failed: %s", err) - } +func TestProblemCRUD(t *testing.T) { - params := ProblemGetParams{ - ObjectIDs: []string{"20143"}, - // ... Add other fields as needed - } + var z Context - problems, _, err := z.ProblemGet(params) - if err != nil { - t.Fatalf("ProblemGet failed: %s", err) - } + // Login + loginTest(&z, t) + defer logoutTest(&z, t) - if len(problems) == 0 { - t.Fatalf("No problems found") - } + // Get + testProblemGet(t, z) +} - fmt.Println("Problems list:") - for _, p := range problems { - fmt.Println(p) - } +func testProblemGet(t *testing.T, z Context) { + + pObjects, _, err := z.ProblemGet(ProblemGetParams{ + //ObjectIDs: []int{20143}, + // ... Add other fields as needed + }) - // ... Add more tests to validate the results + if err != nil { + t.Error("Problem get error:", err) + } else { + if len(pObjects) == 0 { + t.Error("Problem get error: unable to find problems") + } else { + t.Logf("Problem get: success") + } + } } diff --git a/zabbix.go b/zabbix.go index aebb29a..d1f9b1d 100644 --- a/zabbix.go +++ b/zabbix.go @@ -4,7 +4,7 @@ import ( "encoding/json" "errors" "fmt" - "io/ioutil" + "io" "net/http" "strings" @@ -155,7 +155,7 @@ func (z *Context) httpPost(in interface{}, out interface{}) (int, error) { defer res.Body.Close() if res.StatusCode != 200 { - if bodyBytes, err := ioutil.ReadAll(res.Body); err == nil { + if bodyBytes, err := io.ReadAll(res.Body); err == nil { return res.StatusCode, errors.New(string(bodyBytes)) } } else {