diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b016305..4f36c57 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,7 +11,7 @@ jobs: name: Build strategy: matrix: - go-version: [1.12.x, 1.13.x] + go-version: [1.12.x, 1.13.x, 1.14.x] platform: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.platform }} steps: diff --git a/cmd/check_fritz/main.go b/cmd/check_fritz/main.go index 49263fa..0889ca6 100644 --- a/cmd/check_fritz/main.go +++ b/cmd/check_fritz/main.go @@ -3,13 +3,12 @@ package main import ( "fmt" "os" - "strconv" - cmdline "github.com/galdor/go-cmdline" + "github.com/urfave/cli/v2" ) // program version -var version = "1.1.0" +const version = "1.1.0" // internal exit codes const ( @@ -36,7 +35,7 @@ type ArgumentInformation struct { Modelgroup *string } -func createRequiredArgumentInformation(hostname string, port string, username string, password string, method string, timeout string, modelgroup string) ArgumentInformation { +func createRequiredArgumentInformation(hostname string, port string, username string, password string, method string, timeout int, modelgroup string) ArgumentInformation { var ai ArgumentInformation ai.Hostname = &hostname @@ -45,47 +44,23 @@ func createRequiredArgumentInformation(hostname string, port string, username st ai.Password = &password ai.Method = &method ai.Modelgroup = &modelgroup - - ai.createTimeout(timeout) + ai.Timeout = &timeout return ai } -func (ai *ArgumentInformation) createWarningThreshold(warning string) { - warn, err := strconv.ParseFloat(warning, 64) - - if HandleError(err) { - return - } - - ai.Warning = &warn - +func (ai *ArgumentInformation) createWarningThreshold(warning float64) { + ai.Warning = &warning } -func (ai *ArgumentInformation) createCriticalThreshold(critical string) { - crit, err := strconv.ParseFloat(critical, 64) - - if HandleError(err) { - return - } - - ai.Critical = &crit +func (ai *ArgumentInformation) createCriticalThreshold(critical float64) { + ai.Critical = &critical } func (ai *ArgumentInformation) createInputVariable(v string) { ai.InputVariable = &v } -func (ai *ArgumentInformation) createTimeout(t string) { - timeout, err := strconv.Atoi(t) - - if HandleError(err) { - return - } - - ai.Timeout = &timeout -} - func printVersion() { fmt.Println("check_fritz v" + version) GlobalReturnCode = exitOk @@ -121,94 +96,192 @@ func HandleError(err error) bool { return false } -func main() { - cmdline := cmdline.New() - - cmdline.AddOption("H", "hostname", "value", "Specifies the hostname.") - cmdline.AddOption("P", "port", "value", "Specifies the SSL port.") - cmdline.AddOption("u", "username", "value", "Specifies the username.") - cmdline.AddOption("p", "password", "value", "Specifies the password.") - cmdline.AddOption("m", "method", "value", "Specifies the check method.") - cmdline.AddOption("w", "warning", "value", "Specifies the warning threshold.") - cmdline.AddOption("c", "critical", "value", "Specifies the critical threshold.") - cmdline.AddOption("a", "ain", "value", "Specifies the AIN for smart devices.") - cmdline.AddOption("t", "timeout", "value", "Specifies the timeout for the request.") - cmdline.AddOption("M", "modelgroup", "value", "Specifies the Fritz!Box model group (DSL or Cable).") - - cmdline.AddFlag("V", "version", "Returns the version") - - cmdline.SetOptionDefault("hostname", "fritz.box") - cmdline.SetOptionDefault("port", "49443") - cmdline.SetOptionDefault("username", "dslf-config") - cmdline.SetOptionDefault("method", "connection_status") - cmdline.SetOptionDefault("timeout", "90") - cmdline.SetOptionDefault("modelgroup", "DSL") - - cmdline.Parse(os.Args) - - if cmdline.IsOptionSet("version") { - printVersion() - } else { - - hostname := cmdline.OptionValue("hostname") - port := cmdline.OptionValue("port") - username := cmdline.OptionValue("username") - password := cmdline.OptionValue("password") - method := cmdline.OptionValue("method") - timeout := cmdline.OptionValue("timeout") - modelgroup := cmdline.OptionValue("modelgroup") - - aI := createRequiredArgumentInformation(hostname, port, username, password, method, timeout, modelgroup) - - if cmdline.IsOptionSet("warning") { - aI.createWarningThreshold(cmdline.OptionValue("warning")) - } - - if cmdline.IsOptionSet("critical") { - aI.createCriticalThreshold(cmdline.OptionValue("critical")) - } - - if cmdline.IsOptionSet("ain") { - aI.createInputVariable(cmdline.OptionValue("ain")) - } - - if !checkRequiredFlags(&aI) { - os.Exit(exitUnknown) - } - - switch *aI.Method { - case "connection_status": - CheckConnectionStatus(aI) - case "connection_uptime": - CheckConnectionUptime(aI) - case "device_uptime": - CheckDeviceUptime(aI) - case "device_update": - CheckDeviceUpdate(aI) - case "downstream_max": - CheckDownstreamMax(aI) - case "upstream_max": - CheckUpstreamMax(aI) - case "downstream_current": - CheckDownstreamCurrent(aI) - case "downstream_usage": - CheckDownstreamUsage(aI) - case "upstream_usage": - CheckUpstreamUsage(aI) - case "upstream_current": - CheckUpstreamCurrent(aI) - case "smart_heatertemperatur": - CheckSpecificSmartHeaterTemperatur(aI) - case "smart_socketpower": - CheckSpecificSmartSocketPower(aI) - case "smart_socketenergy": - CheckSpecificSmartSocketEnergy(aI) - case "smart_status": - CheckSpecificSmartStatus(aI) - default: - fmt.Println("Unknown method.") - GlobalReturnCode = exitUnknown - } +func checkMain(c *cli.Context) error { + + type param struct { + Hostname string + Port string + Username string + Password string + Method string + Timeout int + ModelGroup string } + + p := param{} + + p.Hostname = c.String("hostname") + p.Port = c.String("port") + p.Username = c.String("username") + + if c.IsSet("password") { + p.Password = c.String("password") + } + + p.Method = c.String("method") + p.Timeout = c.Int("timeout") + p.ModelGroup = c.String("modelgroup") + + argInfo := createRequiredArgumentInformation(p.Hostname, p.Port, p.Username, p.Password, p.Method, p.Timeout, p.ModelGroup) + + if c.IsSet("warning") { + argInfo.createWarningThreshold(c.Float64("warning")) + } + + if c.IsSet("critical") { + argInfo.createCriticalThreshold(c.Float64("critical")) + } + + if c.IsSet("ain") { + argInfo.createInputVariable(c.String("ain")) + } + + if !checkRequiredFlags(&argInfo) { + os.Exit(exitUnknown) + } + + switch *argInfo.Method { + case "connection_status": + CheckConnectionStatus(argInfo) + case "connection_uptime": + CheckConnectionUptime(argInfo) + case "device_uptime": + CheckDeviceUptime(argInfo) + case "device_update": + CheckDeviceUpdate(argInfo) + case "downstream_max": + CheckDownstreamMax(argInfo) + case "upstream_max": + CheckUpstreamMax(argInfo) + case "downstream_current": + CheckDownstreamCurrent(argInfo) + case "downstream_usage": + CheckDownstreamUsage(argInfo) + case "upstream_usage": + CheckUpstreamUsage(argInfo) + case "upstream_current": + CheckUpstreamCurrent(argInfo) + case "smart_heatertemperatur": + CheckSpecificSmartHeaterTemperatur(argInfo) + case "smart_socketpower": + CheckSpecificSmartSocketPower(argInfo) + case "smart_socketenergy": + CheckSpecificSmartSocketEnergy(argInfo) + case "smart_status": + CheckSpecificSmartStatus(argInfo) + default: + fmt.Println("Unknown method.") + GlobalReturnCode = exitUnknown + } + os.Exit(GlobalReturnCode) + + return nil +} + +func main() { + app := &cli.App{ + Action: checkMain, + Name: "check_fritz", + Usage: "Check plugin to monitor a Fritz!Box", + Version: version, + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "hostname", + Aliases: []string{"H"}, + Value: "fritz.box", + DefaultText: "fritz.box", + Usage: "Specifies the hostname.", + }, + &cli.StringFlag{ + Name: "port", + Aliases: []string{"P"}, + Value: "49443", + DefaultText: "49443", + Usage: "Specifies the SSL port.", + }, + &cli.StringFlag{ + Name: "username", + Aliases: []string{"u"}, + Value: "dslf-config", + DefaultText: "dslf-config", + Usage: "Specifies the username.", + }, + &cli.StringFlag{ + Name: "password", + Aliases: []string{"p"}, + Usage: "Specifies the password.", + }, + &cli.StringFlag{ + Name: "method", + Aliases: []string{"m"}, + Value: "connection_status", + DefaultText: "connection_status", + Usage: "Specifies the check method.", + }, + &cli.StringFlag{ + Name: "ain", + Aliases: []string{"a"}, + Usage: "Specifies the AIN for smart devices.", + }, + &cli.IntFlag{ + Name: "timeout", + Aliases: []string{"t"}, + Value: 90, + DefaultText: "90", + Usage: "Specifies the timeout for requests.", + }, + &cli.StringFlag{ + Name: "modelgroup", + Value: "DSL", + DefaultText: "DSL", + Usage: "Specifies the Fritz!Bpx model group (DSL or Cable).", + }, + &cli.Float64Flag{ + Name: "warning", + Aliases: []string{"w"}, + Usage: "Specifies the warning threshold.", + }, + &cli.Float64Flag{ + Name: "critical", + Aliases: []string{"c"}, + Usage: "Specifies the critical threshold.", + }, + }, + } + + cli.AppHelpTemplate = `NAME: + + {{.Name}} - {{.Usage}} + +USAGE: + check_fritz [options...] + +OPTIONS: + + {{range .VisibleFlags}}{{.}} + {{end}} + +METHODS: + connection_status WAN connection status, + connection_uptime WAN connection uptime (in seconds), + device_uptime device uptime (in seconds), + device_update update state, + downstream_max maximum downstream, + upstream_max maximum downstream, + downstream_current current downstream, + upstream_current current upstream, + downstream_usage current downstream usage, + upstream_usage current upstream usage, + smart_heattemperatur current temperature of a a radiator thermostat (requires AIN), + smart_socketpower current power consumption of a socket switch (requires AIN), + smart_status current smart device status (requires AIN) +` + + cli.VersionFlag = &cli.BoolFlag{ + Name: "version", Aliases: []string{"V"}, + Usage: "print the version", + } + + app.Run(os.Args) } diff --git a/go.mod b/go.mod index 034872b..3208776 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,4 @@ module github.com/mcktr/check_fritz go 1.12 -require github.com/galdor/go-cmdline v1.1.0 +require github.com/urfave/cli/v2 v2.2.0 diff --git a/go.sum b/go.sum index 89b0a33..033734f 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,13 @@ -github.com/galdor/go-cmdline v1.1.0 h1:r9w9qQwgx4Oms9Y+9R1BZBGV+TLa50b8Tkwk8Gs3R28= -github.com/galdor/go-cmdline v1.1.0/go.mod h1:7T9Fsb7p6o2E/uV6qZIgqLRDGdfmkHzzg+LvEQrmsm0= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= +github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=