diff --git a/go.mod b/go.mod index 255d6a5..0926a49 100644 --- a/go.mod +++ b/go.mod @@ -4,12 +4,14 @@ go 1.22.6 require ( github.com/gin-gonic/gin v1.10.0 + github.com/influxdata/influxdb-client-go/v2 v2.14.0 github.com/jmoiron/sqlx v1.4.0 github.com/spf13/viper v1.19.0 modernc.org/sqlite v1.32.0 ) require ( + github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/bytedance/sonic v1.11.6 // indirect github.com/bytedance/sonic/loader v0.1.1 // indirect github.com/cloudwego/base64x v0.1.4 // indirect @@ -25,6 +27,7 @@ require ( github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect @@ -34,6 +37,7 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/oapi-codegen/runtime v1.0.0 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect diff --git a/go.sum b/go.sum index 2ddb7a3..dba30ef 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,9 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= +github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= @@ -47,10 +51,15 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/influxdata/influxdb-client-go/v2 v2.14.0 h1:AjbBfJuq+QoaXNcrova8smSjwJdUHnwvfjMF71M1iI4= +github.com/influxdata/influxdb-client-go/v2 v2.14.0/go.mod h1:Ahpm3QXKMJslpXl3IftVLVezreAUtBOTZssDrjZEFHI= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -78,6 +87,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/oapi-codegen/runtime v1.0.0 h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo= +github.com/oapi-codegen/runtime v1.0.0/go.mod h1:LmCUMQuPB4M/nLXilQXhHw+BLZdDb18B34OO356yJ/A= github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -101,6 +112,7 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= diff --git a/internal/conf/getconfig.go b/internal/conf/getconfig.go index 30bbc62..6a36647 100644 --- a/internal/conf/getconfig.go +++ b/internal/conf/getconfig.go @@ -20,6 +20,7 @@ func Get(path string) (config models.Conf) { viper.SetDefault("IFACES", "") viper.SetDefault("TIMEOUT", 60) viper.SetDefault("TRIM_HIST", 48) + viper.SetDefault("INFLUX_ENABLE", false) viper.SetConfigFile(path) viper.SetConfigType("yaml") @@ -38,6 +39,12 @@ func Get(path string) (config models.Conf) { config.Ifaces = viper.Get("IFACES").(string) config.Timeout = viper.GetInt("TIMEOUT") config.TrimHist = viper.GetInt("TRIM_HIST") + config.InfluxEnable = viper.GetBool("INFLUX_ENABLE") + config.InfluxSkipTLS = viper.GetBool("INFLUX_SKIP_TLS") + config.InfluxAddr, _ = viper.Get("INFLUX_ADDR").(string) + config.InfluxToken, _ = viper.Get("INFLUX_TOKEN").(string) + config.InfluxOrg, _ = viper.Get("INFLUX_ORG").(string) + config.InfluxBucket, _ = viper.Get("INFLUX_BUCKET").(string) return config } @@ -59,6 +66,13 @@ func Write(config models.Conf) { viper.Set("TIMEOUT", config.Timeout) viper.Set("TRIM_HIST", config.TrimHist) + viper.Set("influx_enable", config.InfluxEnable) + viper.Set("influx_skip_tls", config.InfluxSkipTLS) + viper.Set("influx_addr", config.InfluxAddr) + viper.Set("influx_token", config.InfluxToken) + viper.Set("influx_org", config.InfluxOrg) + viper.Set("influx_bucket", config.InfluxBucket) + err := viper.WriteConfig() check.IfError(err) } diff --git a/internal/influx/influx.go b/internal/influx/influx.go new file mode 100644 index 0000000..7d5fc06 --- /dev/null +++ b/internal/influx/influx.go @@ -0,0 +1,40 @@ +package influx + +import ( + "context" + "crypto/tls" + "fmt" + // "log" + "strings" + + "github.com/influxdata/influxdb-client-go/v2" + + "github.com/aceberg/WatchYourLAN/internal/check" + "github.com/aceberg/WatchYourLAN/internal/models" +) + +// Add - write data to InfluxDB2 +func Add(appConfig models.Conf, oneHist models.Host) { + + client := influxdb2.NewClientWithOptions(appConfig.InfluxAddr, appConfig.InfluxToken, + influxdb2.DefaultOptions(). + SetUseGZip(true). + SetTLSConfig(&tls.Config{ + InsecureSkipVerify: appConfig.InfluxSkipTLS, + })) + + writeAPI := client.WriteAPIBlocking(appConfig.InfluxOrg, appConfig.InfluxBucket) + + // Escape special characters in strings + oneHist.Name = strings.ReplaceAll(oneHist.Name, " ", "\\ ") + oneHist.Name = strings.ReplaceAll(oneHist.Name, ",", "\\,") + oneHist.Name = strings.ReplaceAll(oneHist.Name, "=", "\\=") + + line := fmt.Sprintf("WatchYourLAN,IP=%s,iface=%s,name=%s,mac=%s,known=%d state=%d", oneHist.IP, oneHist.Iface, oneHist.Name, oneHist.Mac, oneHist.Known, oneHist.Now) + // log.Println("LINE:", line) + + err := writeAPI.WriteRecord(context.Background(), line) + check.IfError(err) + + client.Close() +} diff --git a/internal/models/models.go b/internal/models/models.go index 743ac28..6f517e5 100644 --- a/internal/models/models.go +++ b/internal/models/models.go @@ -2,19 +2,24 @@ package models // Conf - app config type Conf struct { - Host string - Port string - Theme string - Color string - DirPath string - ConfPath string - DBPath string - NodePath string - Ifaces string - // Scaner string - ArpArgs string - Timeout int - TrimHist int + Host string + Port string + Theme string + Color string + DirPath string + ConfPath string + DBPath string + NodePath string + Ifaces string + ArpArgs string + Timeout int + TrimHist int + InfluxEnable bool + InfluxAddr string + InfluxToken string + InfluxOrg string + InfluxBucket string + InfluxSkipTLS bool } // Host - one host diff --git a/internal/web/config.go b/internal/web/config.go index bfe8e69..b2b1578 100644 --- a/internal/web/config.go +++ b/internal/web/config.go @@ -49,3 +49,30 @@ func saveConfigHandler(c *gin.Context) { c.Redirect(http.StatusFound, "/config") } + +func saveInfluxHandler(c *gin.Context) { + + appConfig.InfluxAddr = c.PostForm("addr") + appConfig.InfluxToken = c.PostForm("token") + appConfig.InfluxOrg = c.PostForm("org") + appConfig.InfluxBucket = c.PostForm("bucket") + enable := c.PostForm("enable") + skip := c.PostForm("skip") + + if enable == "on" { + appConfig.InfluxEnable = true + } else { + appConfig.InfluxEnable = false + } + if skip == "on" { + appConfig.InfluxSkipTLS = true + } else { + appConfig.InfluxSkipTLS = false + } + + conf.Write(appConfig) + + slog.Info("writing new config to " + appConfig.ConfPath) + + c.Redirect(http.StatusFound, "/config") +} diff --git a/internal/web/scan.go b/internal/web/scan.go index dec5f08..abbf5a4 100644 --- a/internal/web/scan.go +++ b/internal/web/scan.go @@ -6,6 +6,7 @@ import ( "github.com/aceberg/WatchYourLAN/internal/arp" "github.com/aceberg/WatchYourLAN/internal/db" + "github.com/aceberg/WatchYourLAN/internal/influx" "github.com/aceberg/WatchYourLAN/internal/models" ) @@ -72,6 +73,9 @@ func compareHosts(foundHosts []models.Host) { aHost.Date = time.Now().Format("2006-01-02 15:04:05") db.Insert(appConfig.DBPath, "history", aHost) + if appConfig.InfluxEnable { + influx.Add(appConfig, aHost) + } } for _, fHost := range foundHostsMap { diff --git a/internal/web/templates/config.html b/internal/web/templates/config.html index 779a23a..9cc5a6d 100644 --- a/internal/web/templates/config.html +++ b/internal/web/templates/config.html @@ -66,6 +66,60 @@