From c75670b8cebec1eb8a6fb39f884a8bfd442ec061 Mon Sep 17 00:00:00 2001 From: Justin Hammond Date: Mon, 17 Oct 2022 21:43:32 +0800 Subject: [PATCH] add Zabbix RSS Feed --- conf/app.conf | 6 +- controllers/zabbix.go | 98 ++++++++++++++++++ go.mod | 2 + go.sum | 5 + models/zabbix.go | 141 ++++++++++++++++++++++++++ routers/commentsRouter_controllers.go | 9 ++ routers/router.go | 5 + 7 files changed, 265 insertions(+), 1 deletion(-) create mode 100644 controllers/zabbix.go create mode 100644 models/zabbix.go diff --git a/conf/app.conf b/conf/app.conf index 0d8c59a..fe1684a 100644 --- a/conf/app.conf +++ b/conf/app.conf @@ -11,4 +11,8 @@ username = "fish" pat = ${FOREMAN_PAT} host = "foreman.dmz.dynam.ac" [rundeck] -osuser = "root" \ No newline at end of file +osuser = "root" +[zabbix] +username = "fish" +pat = ${ZABBIX_PAT} +host = "http://zabbix.dmz.dynam.ac/zabbix" diff --git a/controllers/zabbix.go b/controllers/zabbix.go new file mode 100644 index 0000000..708901c --- /dev/null +++ b/controllers/zabbix.go @@ -0,0 +1,98 @@ +package controllers + +import ( + "Foreman-Gateway/models" + "fmt" + "strconv" + "time" + + "github.com/beego/beego/v2/core/config" + "github.com/beego/beego/v2/core/logs" + beego "github.com/beego/beego/v2/server/web" + "github.com/gorilla/feeds" +) + +// Operations about object +type ZabbixController struct { + beego.Controller +} + + +// @Title GetAll +// @Description get all objects +// @Success 200 {object} models.Object +// @Failure 403 :objectId is empty +// @router / [get] +func (o *ZabbixController) GetAll() { + + var q []models.Problems + var err error; + if q, err = models.GetProblems(); err != nil { + logs.Warn("Failed to Get All Problems"); + o.Data["content"] = "Failed to Get All Hosts"; + o.Abort("500") + } else { + host, _ := config.String("zabbix::host"); + feed := &feeds.Feed{ + Title: "Zabbix Problems", + Link: &feeds.Link{Href: host}, + Description: "Zabbix Problems", + Created: time.Now(), + } + for _, item := range q { + ts, _ := strconv.ParseInt(item.LastChange, 10, 0) + feed.Items = append(feed.Items, &feeds.Item{ + Title: fmt.Sprintf("%s: %s", item.Hosts[0].Name, item.Description), + Link: &feeds.Link{Href: fmt.Sprintf("%s/tr_events.php?triggerid=%s&eventid=%s", host, item.TriggerID, item.LastEvent.EventID)}, + Description: item.Description, + Created: time.Unix(ts, 0), + }) + } + rss, err := feed.ToRss() + if err != nil { + logs.Warn("Failed to Generate RSS"); + o.Data["content"] = "Failed to Generate RSS"; + o.Abort("500") + } + fmt.Printf("%+v", rss) + o.Ctx.ResponseWriter.Header().Set("Content-Type", "application/rss+xml") + o.Ctx.WriteString(rss) +// o.Resp(rss) + + } +} + + +// @Title Update +// @Description update the object +// @Param objectId path string true "The objectid you want to update" +// @Param body body models.Object true "The body" +// @Success 200 {object} models.Object +// @Failure 403 :objectId is empty +// @router /:objectId [put] +//func (o *ObjectController) Put() { +// objectId := o.Ctx.Input.Param(":objectId") +// var ob models.Object +// json.Unmarshal(o.Ctx.Input.RequestBody, &ob) +// +// err := models.Update(objectId, ob.Score) +// if err != nil { +// o.Data["json"] = err.Error() +// } else { +// o.Data["json"] = "update success!" +// } +// o.ServeJSON() +//} + +// @Title Delete +// @Description delete the object +// @Param objectId path string true "The objectId you want to delete" +// @Success 200 {string} delete success! +// @Failure 403 objectId is empty +// @router /:objectId [delete] +//func (o *ObjectController) Delete() { +// objectId := o.Ctx.Input.Param(":objectId") +// models.Delete(objectId) +// o.Data["json"] = "delete success!" +// o.ServeJSON() +//} diff --git a/go.mod b/go.mod index 9b9f847..f8b0a58 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,8 @@ go 1.16 require github.com/beego/beego/v2 v2.0.5 require ( + github.com/cavaliercoder/go-zabbix v0.0.0-20220606012333-8601f92dd2eb + github.com/gorilla/feeds v1.1.1 github.com/shurcooL/graphql v0.0.0-20200928012149-18c5c3165e3a github.com/smartystreets/goconvey v1.7.2 ) diff --git a/go.sum b/go.sum index 8deedc1..758df13 100644 --- a/go.sum +++ b/go.sum @@ -66,6 +66,8 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB github.com/bradfitz/gomemcache v0.0.0-20190913173617-a41fca850d0b/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA= github.com/casbin/casbin v1.9.1/go.mod h1:z8uPsfBJGUsnkagrt3G8QvjgTKFMBJ32UP8HpZllfog= github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cavaliercoder/go-zabbix v0.0.0-20220606012333-8601f92dd2eb h1:2/mD6QqRZnjl0446Vqo8ojXOFJn9WqCHWbXo8cYjIjw= +github.com/cavaliercoder/go-zabbix v0.0.0-20220606012333-8601f92dd2eb/go.mod h1:o9iZ0ep18zjkTdG1yoCmBZSMAWo2qUXVMxqmEl+6GLo= github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -205,6 +207,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/feeds v1.1.1 h1:HwKXxqzcRNg9to+BbvJog4+f3s/xzvtZXICcQGutYfY= +github.com/gorilla/feeds v1.1.1/go.mod h1:Nk0jZrvPFZX1OBe5NPiddPw7CfwF6Q9eqzaBbaightA= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -260,6 +264,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= diff --git a/models/zabbix.go b/models/zabbix.go new file mode 100644 index 0000000..0f7182b --- /dev/null +++ b/models/zabbix.go @@ -0,0 +1,141 @@ +package models + +import ( + "context" + + "net/http" + "time" + + "github.com/beego/beego/v2/client/cache" + "github.com/beego/beego/v2/core/config" + "github.com/beego/beego/v2/core/logs" + "github.com/cavaliercoder/go-zabbix" +) + +var ( + zbcache cache.Cache + session *zabbix.Session +) + +func init() { + zbcache, _ = cache.NewCache("memory", `{"interval":20}`); + var host string; + var user string; + var pass string; + var err error; + if host, err = config.String("zabbix::host"); err != nil { + logs.Critical("Zabbix host is not Set", err); + } + if user, err = config.String("zabbix::username"); err != nil { + logs.Critical("Zabbix Username is not Set", err); + } + if pass, err = config.String("zabbix::pat"); err != nil { + logs.Critical("Zabbix PAT is not Set", err); + } + logs.Informational("Using ", host, "For Zabbix"); + + client := &http.Client{ + Transport: &http.Transport{}, + } + + cache := zabbix.NewSessionFileCache().SetFilePath("./zabbix_session") + session, err = zabbix.CreateClient(host + "/api_jsonrpc.php"). + WithCache(cache). + WithHTTPClient(client). + WithCredentials(user, pass). + Connect() + if err != nil { + logs.Critical("Zabbix Connection Failed", err); + } + +} +type Problems struct { + Comments string `json:"comments,omitempty"` + CorrelationMode string `json:"correlation_mode,omitempty"` + CorrelationTag string `json:"correlation_tag,omitempty"` + Description string `json:"description,omitempty"` + Error string `json:"error,omitempty"` + EventName string `json:"event_name,omitempty"` + Expression string `json:"expression,omitempty"` + Flags string `json:"flags,omitempty"` + Hosts []struct { + AutoCompress string `json:"auto_compress,omitempty"` + CustomInterfaces string `json:"custom_interfaces,omitempty"` + Description string `json:"description,omitempty"` + Flags string `json:"flags,omitempty"` + Host string `json:"host,omitempty"` + HostID string `json:"hostid,omitempty"` + InventoryMode string `json:"inventory_mode,omitempty"` + IPMIAuthType string `json:"ipmi_authtype,omitempty"` + IPMIPassword string `json:"ipmi_password,omitempty"` + IPMIPrivilege string `json:"ipmi_privilege,omitempty"` + IPMIUsername string `json:"ipmi_username,omitempty"` + MainenanceFrom string `json:"maintenance_from,omitempty"` + MaintenanceStatus string `json:"maintenance_status,omitempty"` + MaintenanceType string `json:"maintenance_type,omitempty"` + MaintenanceID string `json:"maintenanceid,omitempty"` + Name string `json:"name,omitempty"` + ProxyAddress string `json:"proxy_address,omitempty"` + ProxyHostID string `json:"proxy_hostid,omitempty"` + Status string `json:"status,omitempty"` + TemplateID string `json:"templateid,omitempty"` + TLSAccept string `json:"tls_accept,omitempty"` + TLSConnect string `json:"tls_connect,omitempty"` + TLSIssuer string `json:"tls_issuer,omitempty"` + TLSSubject string `json:"tls_subject,omitempty"` + UUID string `json:"uuid,omitempty"` + } + LastEvent struct { + Acknowledged string `json:"acknowledged,omitempty"` + Clock string `json:"clock,omitempty"` + EventID string `json:"eventid,omitempty"` + Name string `json:"name,omitempty"` + NS string `json:"ns,omitempty"` + Object string `json:"object,omitempty"` + ObjectID string `json:"objectid,omitempty"` + Severity string `json:"severity,omitempty"` + Source string `json:"source,omitempty"` + Value string `json:"value,omitempty"` + } + LastChange string `json:"lastchange,omitempty"` + ManualClose string `json:"manual_close,omitempty"` + OpData string `json:"opdata,omitempty"` + Priority string `json:"priority,omitempty"` + RecoveryExpression string `json:"recovery_expression,omitempty"` + RecoveryMode string `json:"recovery_mode,omitempty"` + State string `json:"state,omitempty"` + Status string `json:"status,omitempty"` + TemplateID string `json:"templateid,omitempty"` + TriggerID string `json:"triggerid,omitempty"` + Type string `json:"type,omitempty"` + URL string `json:"url,omitempty"` + UUID string `json:"uuid,omitempty"` + Value string `json:"value,omitempty"` + +} + + +func GetProblems() (pb []Problems, err error) { + if exists, _ := zbcache.IsExist(context.Background(), "ProblemCache"); exists { + tmpfm, _ := zbcache.Get(context.Background(), "ProblemCache"); + return tmpfm.([]Problems), nil; + } + logs.Info("Gettting Problem List"); + tp := zabbix.TriggerGetParams{ + ExpandDescription: true, + ExpandComment: true, + ExpandExpression: true, + SelectHosts: zabbix.SelectExtendedOutput, + SelectLastEvent: zabbix.SelectExtendedOutput, + ActiveOnly: true, + MonitoredOnly: true, + } + tp.RecentProblemOnly = true + var problem []Problems + session.Get("trigger.Get", tp, &problem) + + + zbcache.Put(context.Background(), "ProblemCache", problem, time.Minute * 5); + return problem, nil; +} + diff --git a/routers/commentsRouter_controllers.go b/routers/commentsRouter_controllers.go index 0d70b5c..a5e48bd 100644 --- a/routers/commentsRouter_controllers.go +++ b/routers/commentsRouter_controllers.go @@ -16,4 +16,13 @@ func init() { Filters: nil, Params: nil}) + beego.GlobalControllerRouter["Foreman-Gateway/controllers:ZabbixController"] = append(beego.GlobalControllerRouter["Foreman-Gateway/controllers:ZabbixController"], + beego.ControllerComments{ + Method: "GetAll", + Router: "/", + AllowHTTPMethods: []string{"get"}, + MethodParams: param.Make(), + Filters: nil, + Params: nil}) + } diff --git a/routers/router.go b/routers/router.go index 57f3bd9..e3b6c8c 100644 --- a/routers/router.go +++ b/routers/router.go @@ -20,6 +20,11 @@ func init() { &controllers.ForemanController{}, ), ), + beego.NSNamespace("/zabbix/problems", + beego.NSInclude( + &controllers.ZabbixController{}, + ), + ), ) beego.AddNamespace(ns) }