Skip to content

Commit

Permalink
initial implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
kovetskiy committed Jun 23, 2016
0 parents commit 292052f
Showing 8 changed files with 746 additions and 0 deletions.
23 changes: 23 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

import (
"github.com/jinzhu/configor"
)

type Config struct {
Server struct {
Address string `toml:"address" required:"true"`
Username string `toml:"username" required:"true"`
Password string `toml:"password" required:"true"`
} `toml:"server"`
}

func NewConfig(path string) (*Config, error) {
config := &Config{}
err := configor.Load(config, path)
if err != nil {
return nil, err
}

return config, nil
}
53 changes: 53 additions & 0 deletions log.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"fmt"
"strings"

"github.com/kovetskiy/lorg"
)

func getLogger(verbosity int) lorg.Logger {
logger := lorg.NewLog()
logger.SetFormat(lorg.NewFormat("${level:[%s]:left:true} %s"))
if verbosity == 1 {
logger.SetLevel(lorg.LevelDebug)
} else if verbosity == 2 {
logger.SetLevel(lorg.LevelTrace)
}

return logger
}

func fatalf(format string, values ...interface{}) {
logger.Fatalf(wrapNewLines(format, values...))
}

func fatalln(value interface{}) {
logger.Fatal(wrapNewLines("%s", value))
}

func debugf(format string, values ...interface{}) {
logger.Debugf(wrapNewLines(format, values...))
}

func debugln(value interface{}) {
logger.Debug(wrapNewLines("%s", value))
}

func tracef(format string, values ...interface{}) {
logger.Trace(wrapNewLines(format, values...))
}

func wrapNewLines(format string, values ...interface{}) string {
contents := fmt.Sprintf(format, values...)
contents = strings.TrimSuffix(contents, "\n")
contents = strings.Replace(
contents,
"\n",
"\n"+strings.Repeat(" ", 8),
-1,
)

return contents
}
111 changes: 111 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
package main

import (
"os"

"github.com/kovetskiy/godocs"
"github.com/kovetskiy/lorg"
"github.com/zazab/hierr"
)

var (
version = "1.0"
usage = `zabbixctl ` + version + os.ExpandEnv(`
zabbixctl is tool for working with zabbix server using command line
interface, it provides effective waay for operating on zabbix triggers and
their statuses, i.e. searching, sorting, showing and acknowledging triggers.
zabbixctl must be configurated before using, configuration file usually locates
in ~/.config/zabbixctl.conf and must be written with following syntax:
[server]
address = "zabbix.hostname"
username = "e.kovetskiy"
password = "pa$$word"
Usage:
zabbixctl [-v]... [options] -T [-x]... [<search>]...
zabbixctl -h | --help
zabbixctl --version
Workflow options:
-T --triggers Operate on zabbix triggers.
-k --only-nack Show unacknowledged triggers only.
-x --severity Specify minimum trigger severity.
Once for information, twice for warning,
three for disaster, four for high, five for disaster.
-p --problem Show triggers that have a problem state.
-r --recent Show triggers that have recently been in a problem state.
-s --since <date> Show triggers that have changed their state after
the given time.
[default: 7 days ago]
-u --until <date> Show triggers that have changed their state before
the given time.
-m --maintenance Show hosts in maintenance.
-i --sort <fields> Show triggers sorted by specified fields.
[default: lastchange,priority]
-o --order <order> Show triggers in specified order.
[default: DESC]
-n --limit <count> Show specified amount of triggers.
[default: 0]
-f --noconfirm Do not prompt acknowledge confirmation dialog.
-a --acknowledge Acknowledge triggers.
Common options:
-c --config <path> Use specified configuration file .
[default: $HOME/.config/zabbixctl.conf]
-v --verbosity Specify program output verbosity.
Once for debug, twice for trace.
-h --help Show this screen.
--version Show version.
`)
)

var (
logger lorg.Logger
)

func main() {
args, err := godocs.Parse(usage, version, godocs.UsePager)
if err != nil {
panic(err)
}

var (
verbosity = args["--verbosity"].(int)
configPath = args["--config"].(string)
)

logger = getLogger(verbosity)

config, err := NewConfig(configPath)
if err != nil {
fatalln(
hierr.Errorf(
err,
"problem with configuration file using %s",
configPath,
),
)
}

zabbix, err := NewZabbix(
config.Server.Address,
config.Server.Username,
config.Server.Password,
)
if err != nil {
fatalln(err)
}

switch {
case args["--triggers"].(bool):
err = handleModeTriggers(zabbix, config, args)
}

if err != nil {
fatalln(err)
}
}
37 changes: 37 additions & 0 deletions responses.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package main

import "github.com/seletskiy/hierr"

type Response interface {
Error() error
}

type ResponseRaw struct {
Err struct {
Data string `json:"data"`
Message string `json:"message"`
} `json:"error"`

Result interface{} `json:"result"`
}

func (response *ResponseRaw) Error() error {
if response.Err.Data != "" && response.Err.Message != "" {
return hierr.Push(
response.Err.Message,
response.Err.Data,
)
}

return nil
}

type ResponseTriggersList struct {
ResponseRaw
Data map[string]Trigger `json:"result"`
}

type ResponseLogin struct {
ResponseRaw
Token string `json:"result"`
}
28 changes: 28 additions & 0 deletions severity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package main

type Severity int

var (
SeverityInformation Severity = 1
SeverityWarning Severity = 2
SeverityAverage Severity = 3
SeverityHigh Severity = 4
SeverityDisaster Severity = 5
)

func (priority Severity) String() string {
switch priority {
case SeverityInformation:
return "INFO"
case SeverityWarning:
return "WARN"
case SeverityAverage:
return "AVG"
case SeverityHigh:
return "HIGH"
case SeverityDisaster:
return "DISASTER"
default:
return "UNKNOWN"
}
}
85 changes: 85 additions & 0 deletions trigger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package main

import (
"strconv"
"strings"
"time"
)

type Trigger struct {
ID string `json:"triggerid"`
Description string `json:"description"`
Hostname string `json:"host"`
Value string `json:"value"`
LastChange string `json:"lastchange"`
LastEvent struct {
ID string `json:"eventid"`
Acknowledged string `json:"acknowledged"`
} `json:"lastEvent"`
Priority string `json:"priority"`
}

func (trigger *Trigger) String() string {
return trigger.LastEvent.ID + " " +
trigger.Hostname + " " + trigger.Description
}

func (trigger *Trigger) StatusAcknowledge() string {
if trigger.LastEvent.Acknowledged == "1" {
return "ACK"
}

return "NACK"
}

func (trigger *Trigger) StatusProblem() string {
if trigger.Value == "1" {
return "PROBLEM"
}

return "OK"
}

func (trigger *Trigger) Severity() Severity {
value, _ := strconv.Atoi(trigger.Priority)
return Severity(value)
}

func (trigger *Trigger) DateTime() string {
return trigger.date().Format("2006-01-02 15:04:05")
}

func (trigger *Trigger) Age() string {
date := time.Now().Sub(trigger.date())

var (
seconds = int(date.Seconds()) % 60
minutes = int(date.Minutes()) % 60
hours = int(date.Hours())
days = hours / 24
months = days / 30.
)

var units []string

units = addUnit(units, months, "mon")
units = addUnit(units, days%7, "d")
units = addUnit(units, hours%24, "h")
units = addUnit(units, minutes, "m")
units = addUnit(units, seconds, "s")

return strings.Join(units, " ")
}

func (trigger *Trigger) date() time.Time {
date, _ := strconv.ParseInt(trigger.LastChange, 10, 64)
return time.Unix(date, 0)
}

func addUnit(units []string, value int, unit string) []string {
if value > 1 {
units = append(units, strconv.Itoa(value)+unit)
}

return units
}
Loading

0 comments on commit 292052f

Please sign in to comment.