aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--cmd/haminer/haminer.conf16
-rw-r--r--config.go122
-rw-r--r--config_test.go214
-rw-r--r--go.mod4
-rw-r--r--go.sum3
-rw-r--r--testdata/haminer.conf5
7 files changed, 303 insertions, 63 deletions
diff --git a/.gitignore b/.gitignore
index 745b3b6..755fb7c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
/haminer
+/cover.out
+/cover.html
diff --git a/cmd/haminer/haminer.conf b/cmd/haminer/haminer.conf
index 80bd2e0..8bdec74 100644
--- a/cmd/haminer/haminer.conf
+++ b/cmd/haminer/haminer.conf
@@ -1,7 +1,8 @@
+[haminer]
##
## Set default listen address in UDP.
##
-## Format: <ADDR:PORT>
+## Format: ADDR [ ":" PORT ]
## Default: 127.0.0.1:5140
##
## Examples,
@@ -15,11 +16,12 @@
## List of HAProxy backend to be accepted and forwarded to Influxdb. Each
## backend name is separated by comma.
##
-## Format: [name],...
+## Format: [ name ] *[ "," name ]
## Default: "", no filter (all backend are accepted).
##
## Examples,
-## accept_backend=api_01,api_02
+##
+## accept_backend=api_01,api_02
##
#accept_backend=
@@ -28,13 +30,13 @@
## Parse HTTP request header in log file generated by "capture request header
## ..." option.
##
-## Format: name | ...
+## Format: [ name ] *["|" name]
## The name should contains only alphabets and underscore.
## Default: "" (empty)
##
## Examples,
##
-## capture_request_header = host | referer
+## capture_request_header = host | referrer
##
#capture_request_header=
@@ -47,8 +49,8 @@
## Default: "", empty. If empty the log will not forwarded to Influxdb.
##
## Examples,
-##influxdb_api_write=http://127.0.0.1:8086/write?db=haminer&u=haminer&p=haminer
-##influxdb_api_write=http://192.168.56.10:8086/write?db=haminer&u=haminer&p=haminer&precision=ns
+##
+## influxdb_api_write=http://127.0.0.1:8086/write?db=haminer&u=haminer&p=haminer
##
#influxdb_api_write=
diff --git a/config.go b/config.go
index 01f49c9..95b1a44 100644
--- a/config.go
+++ b/config.go
@@ -5,11 +5,11 @@
package haminer
import (
- "bytes"
- "io/ioutil"
"log"
"strconv"
"strings"
+
+ "github.com/shuLhan/share/lib/ini"
)
// List of config keys.
@@ -22,10 +22,9 @@ const (
// List of default config key values.
const (
- DefListenAddr = "127.0.0.1"
- DefListenPort = 5140
- DefInfluxAPIWrite = "http://127.0.0.1:8086/write?db=haproxy"
- DefMaxBufferedLogs = 10
+ defListenAddr = "127.0.0.1"
+ defListenPort = 5140
+ defMaxBufferedLogs = 10
)
//
@@ -53,89 +52,100 @@ type Config struct {
}
//
-// NewConfig will create, initialize, and return new config with defautl
+// NewConfig will create, initialize, and return new config with default
// values.
//
func NewConfig() (cfg *Config) {
return &Config{
- ListenAddr: DefListenAddr,
- ListenPort: DefListenPort,
- MaxBufferedLogs: DefMaxBufferedLogs,
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ }
+}
+
+//
+// Load configuration from file defined by `path`.
+//
+func (cfg *Config) Load(path string) {
+ if len(path) == 0 {
+ return
+ }
+
+ in, err := ini.Open(path)
+ if err != nil {
+ log.Println(err)
+ return
+ }
+
+ v, _ := in.Get("haminer", "", ConfigKeyListen)
+ cfg.SetListen(v)
+
+ v, _ = in.Get("haminer", "", ConfigKeyAcceptBackend)
+ cfg.ParseAcceptBackend(v)
+
+ v, _ = in.Get("haminer", "", ConfigKeyCaptureRequestHeader)
+ cfg.ParseCaptureRequestHeader(v)
+
+ v, _ = in.Get("haminer", "", ConfigKeyInfluxAPIWrite)
+ if len(v) > 0 {
+ cfg.InfluxAPIWrite = v
}
}
//
-// SetListen will parse `v` value as "addr:port", and set config address and port
-// based on it.
+// SetListen will parse `v` value as "addr:port", and set config address and
+// port based on it.
//
func (cfg *Config) SetListen(v string) {
+ if len(v) == 0 {
+ return
+ }
+
var err error
addrPort := strings.Split(v, ":")
switch len(addrPort) {
- case 0:
- return
case 1:
cfg.ListenAddr = addrPort[0]
case 2:
cfg.ListenAddr = addrPort[0]
cfg.ListenPort, err = strconv.Atoi(addrPort[1])
if err != nil {
- cfg.ListenPort = DefListenPort
+ cfg.ListenPort = defListenPort
}
}
}
-//
-// parseCaptureRequestHeader Parse request header names where each name is
-// separated by "|".
-//
-func (cfg *Config) parseCaptureRequestHeader(v []byte) {
- sep := []byte{'|'}
- headers := bytes.Split(v, sep)
- for x := 0; x < len(headers); x++ {
- headers[x] = bytes.TrimSpace(headers[x])
- cfg.RequestHeaders = append(cfg.RequestHeaders, string(headers[x]))
+func (cfg *Config) ParseAcceptBackend(v string) {
+ v = strings.TrimSpace(v)
+ if len(v) == 0 {
+ return
+ }
+
+ for _, v = range strings.Split(v, ",") {
+ if len(v) == 0 {
+ continue
+ }
+ cfg.AcceptBackend = append(cfg.AcceptBackend, strings.TrimSpace(v))
}
}
//
-// Load will read configuration from file defined by `path`.
+// ParseCaptureRequestHeader Parse request header names where each name is
+// separated by "|".
//
-func (cfg *Config) Load(path string) {
- bb, err := ioutil.ReadFile(path)
- if err != nil {
- log.Println(err)
+func (cfg *Config) ParseCaptureRequestHeader(v string) {
+ v = strings.TrimSpace(v)
+ if len(v) == 0 {
return
}
- lines := bytes.Split(bb, []byte("\n"))
-
- for _, line := range lines {
- if len(line) == 0 {
- continue
- }
- if line[0] == '#' {
- continue
- }
-
- kv := bytes.SplitN(line, []byte("="), 2)
- if len(kv) != 2 {
+ headers := strings.Split(v, "|")
+ for x := 0; x < len(headers); x++ {
+ headers[x] = strings.TrimSpace(headers[x])
+ if len(headers[x]) == 0 {
continue
}
-
- switch string(kv[0]) {
- case ConfigKeyListen:
- cfg.SetListen(string(kv[1]))
- case ConfigKeyCaptureRequestHeader:
- cfg.parseCaptureRequestHeader(kv[1])
- case ConfigKeyAcceptBackend:
- v := string(bytes.TrimSpace(kv[1]))
- if len(v) > 0 {
- cfg.AcceptBackend = strings.Split(v, ",")
- }
- case ConfigKeyInfluxAPIWrite:
- cfg.InfluxAPIWrite = string(kv[1])
- }
+ cfg.RequestHeaders = append(cfg.RequestHeaders, headers[x])
}
}
diff --git a/config_test.go b/config_test.go
new file mode 100644
index 0000000..9f595b7
--- /dev/null
+++ b/config_test.go
@@ -0,0 +1,214 @@
+// Copyright 2019, M. Shulhan (ms@kilabit.info). All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package haminer
+
+import (
+ "testing"
+
+ "github.com/shuLhan/share/lib/test"
+)
+
+func TestNewConfig(t *testing.T) {
+ cases := []struct {
+ desc string
+ exp *Config
+ }{{
+ desc: "With default config",
+ exp: &Config{
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ },
+ }}
+
+ for _, c := range cases {
+ t.Log(c.desc)
+
+ got := NewConfig()
+
+ test.Assert(t, "Config", c.exp, got, true)
+ }
+}
+
+func TestLoad(t *testing.T) {
+ cases := []struct {
+ desc string
+ in string
+ exp *Config
+ }{{
+ desc: "With empty path",
+ exp: &Config{
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ },
+ }, {
+ desc: "With path not exist",
+ in: "testdata/notexist.conf",
+ exp: &Config{
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ },
+ }, {
+ desc: "With path exist",
+ in: "testdata/haminer.conf",
+ exp: &Config{
+ ListenAddr: "0.0.0.0",
+ ListenPort: 8080,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ AcceptBackend: []string{
+ "a",
+ "b",
+ },
+ RequestHeaders: []string{
+ "host",
+ "referrer",
+ },
+ InfluxAPIWrite: "http://127.0.0.1:8086/write",
+ },
+ }}
+
+ for _, c := range cases {
+ t.Log(c.desc)
+
+ got := NewConfig()
+ got.Load(c.in)
+
+ test.Assert(t, "Config", c.exp, got, true)
+ }
+}
+
+func TestSetListen(t *testing.T) {
+ cases := []struct {
+ desc string
+ in string
+ exp *Config
+ }{{
+ desc: "With empty listen",
+ exp: &Config{
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ },
+ }, {
+ desc: "With empty port",
+ in: "127.0.0.2",
+ exp: &Config{
+ ListenAddr: "127.0.0.2",
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ },
+ }, {
+ desc: "With no port",
+ in: "127.0.0.3:",
+ exp: &Config{
+ ListenAddr: "127.0.0.3",
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ },
+ }}
+
+ for _, c := range cases {
+ t.Log(c.desc)
+
+ got := NewConfig()
+ got.SetListen(c.in)
+
+ test.Assert(t, "Config", c.exp, got, true)
+ }
+}
+
+func TestParseAcceptBackend(t *testing.T) {
+ cases := []struct {
+ desc string
+ in string
+ exp *Config
+ }{{
+ desc: "With empty value",
+ exp: &Config{
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ },
+ }, {
+ desc: "With no separator",
+ in: "a ; b",
+ exp: &Config{
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ AcceptBackend: []string{
+ "a ; b",
+ },
+ },
+ }, {
+ desc: "With comma at beginning and end",
+ in: ",a,b,",
+ exp: &Config{
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ AcceptBackend: []string{
+ "a", "b",
+ },
+ },
+ }}
+
+ for _, c := range cases {
+ t.Log(c.desc)
+
+ got := NewConfig()
+ got.ParseAcceptBackend(c.in)
+
+ test.Assert(t, "Config", c.exp, got, true)
+ }
+}
+
+func TestParseCaptureRequestHeader(t *testing.T) {
+ cases := []struct {
+ desc string
+ in string
+ exp *Config
+ }{{
+ desc: "With empty value",
+ exp: &Config{
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ },
+ }, {
+ desc: "With no separator",
+ in: "a ; b",
+ exp: &Config{
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ RequestHeaders: []string{
+ "a ; b",
+ },
+ },
+ }, {
+ desc: "With separator at beginning and end",
+ in: "|a|b|",
+ exp: &Config{
+ ListenAddr: defListenAddr,
+ ListenPort: defListenPort,
+ MaxBufferedLogs: defMaxBufferedLogs,
+ RequestHeaders: []string{
+ "a", "b",
+ },
+ },
+ }}
+
+ for _, c := range cases {
+ t.Log(c.desc)
+
+ got := NewConfig()
+ got.ParseCaptureRequestHeader(c.in)
+
+ test.Assert(t, "Config", c.exp, got, true)
+ }
+}
diff --git a/go.mod b/go.mod
index 0ef23ce..6ed0df5 100644
--- a/go.mod
+++ b/go.mod
@@ -1 +1,5 @@
module github.com/shuLhan/haminer
+
+go 1.12
+
+require github.com/shuLhan/share v0.2.0
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..6da22fd
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,3 @@
+github.com/shuLhan/share v0.2.0 h1:xm12WiZ0L9Yj5fNUgxKXfpxl4SJ9VuRdRwbQ5cACeik=
+github.com/shuLhan/share v0.2.0/go.mod h1:SjjW0kmafz7R07V8GP8D9YvTj0jQ4A5LoLVYjC+920U=
+golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
diff --git a/testdata/haminer.conf b/testdata/haminer.conf
new file mode 100644
index 0000000..554b04e
--- /dev/null
+++ b/testdata/haminer.conf
@@ -0,0 +1,5 @@
+[haminer]
+listen = 0.0.0.0:8080
+accept_backend = a , b,
+capture_request_header = host | referrer|
+influxdb_api_write = http://127.0.0.1:8086/write