diff --git a/cfg/cfg.go b/cfg/cfg.go new file mode 100644 index 0000000..e1ad5db --- /dev/null +++ b/cfg/cfg.go @@ -0,0 +1,48 @@ +package cfg + +import ( + "flag" + "fmt" + "os" +) + +const ( + minServerPort = 1000 + maxServerPort = 65535 +) + +type AppSettings struct { + VersionMode bool + MetricsPort int + Fail2BanDbPath string +} + +func Parse() *AppSettings { + appSettings := &AppSettings{} + flag.BoolVar(&appSettings.VersionMode, "version", false, "show version info and exit") + flag.IntVar(&appSettings.MetricsPort, "port", 9191, "port to use for the metrics server") + flag.StringVar(&appSettings.Fail2BanDbPath, "db", "", "path to the fail2ban sqlite database") + + flag.Parse() + appSettings.validateFlags() + return appSettings +} + +func (settings *AppSettings) validateFlags() { + var flagsValid = true + if !settings.VersionMode { + if settings.Fail2BanDbPath == "" { + fmt.Println("missing flag 'db'") + flagsValid = false + } + if settings.MetricsPort < minServerPort || settings.MetricsPort > maxServerPort { + fmt.Printf("invalid server port, must be within %d and %d (found %d)\n", + minServerPort, maxServerPort, settings.MetricsPort) + flagsValid = false + } + } + if !flagsValid { + flag.Usage() + os.Exit(1) + } +} diff --git a/db/db.go b/db/db.go index cd425c4..0d92edc 100644 --- a/db/db.go +++ b/db/db.go @@ -10,7 +10,7 @@ const queryBannedIpsPerJail = "SELECT j.name, (SELECT COUNT(1) FROM bans b WHERE type Fail2BanDB struct { DatabasePath string - sqliteDB *sql.DB + sqliteDB *sql.DB } func MustConnectToDb(databasePath string) *Fail2BanDB { diff --git a/exporter.go b/exporter.go index 19b2d7d..df968c0 100644 --- a/exporter.go +++ b/exporter.go @@ -1,7 +1,9 @@ package main import ( + "fail2ban-prometheus-exporter/cfg" fail2banDb "fail2ban-prometheus-exporter/db" + "fmt" _ "github.com/mattn/go-sqlite3" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" @@ -12,7 +14,11 @@ import ( const namespace = "fail2ban" var ( - db = fail2banDb.MustConnectToDb("fail2ban.sqlite3") + version = "dev" + commit = "none" + date = "unknown" + builtBy = "unknown" + metricUp = prometheus.NewDesc( prometheus.BuildFQName(namespace, "", "up"), "Was the last fail2ban query successful.", @@ -31,6 +37,7 @@ var ( ) type Exporter struct { + db *fail2banDb.Fail2BanDB } func (e *Exporter) Describe(ch chan<- *prometheus.Desc) { @@ -43,12 +50,12 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( metricUp, prometheus.GaugeValue, 1, ) - collectBadIpsPerJailMetrics(ch) - collectBannedIpsPerJailMetrics(ch) + e.collectBadIpsPerJailMetrics(ch) + e.collectBannedIpsPerJailMetrics(ch) } -func collectBadIpsPerJailMetrics(ch chan<- prometheus.Metric) { - jailNameToCountMap, err := db.CountBadIpsPerJail() +func (e *Exporter) collectBadIpsPerJailMetrics(ch chan<- prometheus.Metric) { + jailNameToCountMap, err := e.db.CountBadIpsPerJail() if err != nil { log.Print(err) } @@ -60,8 +67,8 @@ func collectBadIpsPerJailMetrics(ch chan<- prometheus.Metric) { } } -func collectBannedIpsPerJailMetrics(ch chan<- prometheus.Metric) { - jailNameToCountMap, err := db.CountBannedIpsPerJail() +func (e *Exporter) collectBannedIpsPerJailMetrics(ch chan<- prometheus.Metric) { + jailNameToCountMap, err := e.db.CountBannedIpsPerJail() if err != nil { log.Print(err) } @@ -73,12 +80,24 @@ func collectBannedIpsPerJailMetrics(ch chan<- prometheus.Metric) { } } -func main() { - log.Print("starting fail2ban exporter") - - exporter := &Exporter{} - prometheus.MustRegister(exporter) - - http.Handle("/metrics", promhttp.Handler()) - log.Fatal(http.ListenAndServe(":9101", nil)) +func printAppVersion() { + fmt.Println(version) + fmt.Printf(" build date: %s\r\n commit hash: %s\r\n built by: %s\r\n", date, commit, builtBy) +} + +func main() { + appSettings := cfg.Parse() + if appSettings.VersionMode { + printAppVersion() + } else { + log.Print("starting fail2ban exporter") + + exporter := &Exporter{ + db: fail2banDb.MustConnectToDb(appSettings.Fail2BanDbPath), + } + prometheus.MustRegister(exporter) + + http.Handle("/metrics", promhttp.Handler()) + log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", appSettings.MetricsPort), nil)) + } }