From 9ee3aeeb00fc9dedba035db51301c4cd51f7d5e6 Mon Sep 17 00:00:00 2001 From: Ozzie Bock Date: Mon, 22 Mar 2021 10:04:00 -0500 Subject: [PATCH] added tests --- .github/workflows/go-cross.yml | 41 ------------- .github/workflows/main.yml | 67 ---------------------- .golangci.toml | 45 --------------- Makefile | 5 +- gelflog.go | 59 ++++++++++--------- gelflog_test.go | 102 +++++++++++++++++++++++++++++++++ go.mod | 2 +- go.sum | 4 +- vendor/modules.txt | 2 - 9 files changed, 139 insertions(+), 188 deletions(-) delete mode 100644 .github/workflows/go-cross.yml delete mode 100644 .github/workflows/main.yml delete mode 100644 .golangci.toml create mode 100644 gelflog_test.go diff --git a/.github/workflows/go-cross.yml b/.github/workflows/go-cross.yml deleted file mode 100644 index 57c0ec0..0000000 --- a/.github/workflows/go-cross.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: Go Matrix -on: [push, pull_request] - -jobs: - - cross: - name: Go - runs-on: ${{ matrix.os }} - env: - CGO_ENABLED: 0 - - strategy: - matrix: - go-version: [ 1.15, 1.x ] - os: [ubuntu-latest, macos-latest, windows-latest] - - steps: - # https://github.com/marketplace/actions/setup-go-environment - - name: Set up Go ${{ matrix.go-version }} - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go-version }} - - # https://github.com/marketplace/actions/checkout - - name: Checkout code - uses: actions/checkout@v2 - - # https://github.com/marketplace/actions/cache - - name: Cache Go modules - uses: actions/cache@v2 - with: - path: | - ~/go/pkg/mod # Module download cache - ~/.cache/go-build # Build cache (Linux) - ~/Library/Caches/go-build # Build cache (Mac) - '%LocalAppData%\go-build' # Build cache (Windows) - key: ${{ runner.os }}-${{ matrix.go-version }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-${{ matrix.go-version }}-go- - - name: Test - run: go test -v -cover ./... \ No newline at end of file diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml deleted file mode 100644 index 6f220aa..0000000 --- a/.github/workflows/main.yml +++ /dev/null @@ -1,67 +0,0 @@ -name: Main - -on: - push: - branches: - - master - tags: - - v* - pull_request: - -jobs: - - main: - name: Main Process - runs-on: ubuntu-latest - env: - GO_VERSION: 1.15 - GOLANGCI_LINT_VERSION: v1.33.0 - YAEGI_VERSION: v0.9.8 - CGO_ENABLED: 0 - defaults: - run: - working-directory: ${{ github.workspace }}/go/src/github.com/${{ github.repository }} - - steps: - - # https://github.com/marketplace/actions/setup-go-environment - - name: Set up Go ${{ env.GO_VERSION }} - uses: actions/setup-go@v2 - with: - go-version: ${{ env.GO_VERSION }} - - # https://github.com/marketplace/actions/checkout - - name: Check out code - uses: actions/checkout@v2 - with: - path: go/src/github.com/${{ github.repository }} - fetch-depth: 0 - - # https://github.com/marketplace/actions/cache - - name: Cache Go modules - uses: actions/cache@v2 - with: - path: ${{ github.workspace }}/go/pkg/mod - key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: | - ${{ runner.os }}-go- - # https://golangci-lint.run/usage/install#other-ci - - name: Install golangci-lint ${{ env.GOLANGCI_LINT_VERSION }} - run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin ${GOLANGCI_LINT_VERSION} - - - name: Install Yaegi ${{ env.YAEGI_VERSION }} - run: curl -sfL https://raw.githubusercontent.com/traefik/yaegi/master/install.sh | bash -s -- -b $(go env GOPATH)/bin ${YAEGI_VERSION} - - - name: Setup GOPATH - run: go env -w GOPATH=${{ github.workspace }}/go - - - name: Check and get dependencies - run: | - go mod tidy - git diff --exit-code go.mod - # git diff --exit-code go.sum - go mod download - go mod vendor - # git diff --exit-code ./vendor/ - - name: Lint and Tests - run: make \ No newline at end of file diff --git a/.golangci.toml b/.golangci.toml deleted file mode 100644 index 675d7ed..0000000 --- a/.golangci.toml +++ /dev/null @@ -1,45 +0,0 @@ -[run] - timeout = "3m" - skip-files = [] - skip-dirs = [] - -[linters-settings] - - [linters-settings.govet] - check-shadowing = false - - [linters-settings.golint] - min-confidence = 0.0 - - [linters-settings.gocyclo] - min-complexity = 12.0 - - [linters-settings.maligned] - suggest-new = true - - [linters-settings.goconst] - min-len = 3.0 - min-occurrences = 4.0 - - [linters-settings.misspell] - locale = "US" - - [linters-settings.funlen] - lines = 60 # default 60 - statements = 40 # default 40 - -[linters] - enable-all = true - disable = [ - "goerr113", - "nlreturn", - "testpackage", - "paralleltest", - "tparallel", - ] - -[issues] - exclude-use-default = false - max-per-linter = 0 - max-same-issues = 0 - exclude = [] \ No newline at end of file diff --git a/Makefile b/Makefile index 0c7560b..9be9afd 100644 --- a/Makefile +++ b/Makefile @@ -2,10 +2,7 @@ export GO111MODULE=on -default: lint test - -lint: - golangci-lint run +default: test test: go test -v -cover ./... diff --git a/gelflog.go b/gelflog.go index 7174416..55c2c1c 100644 --- a/gelflog.go +++ b/gelflog.go @@ -1,19 +1,15 @@ -package plugin_gelflog +package traefik_gelf_plugin import ( "context" "fmt" "github.com/kjk/betterguid" "gopkg.in/Graylog2/go-gelf.v2/gelf" - "log" "net/http" "os" "time" ) -var GelfWriter *gelf.UDPWriter -var GelfHostname string -var MWConfig *Config // Config holds the plugin configuration. type Config struct { GelfEndpoint string `json:"gelfEndpoint,omitempty"` @@ -39,6 +35,8 @@ type GelfLog struct { Name string Next http.Handler Config *Config + GelfHostname string + GelfWriter *gelf.UDPWriter } // New creates and returns a plugin instance. @@ -49,46 +47,55 @@ func New(_ context.Context, next http.Handler, config *Config, name string) (htt Config: config, } if config == nil { - //log.Fatal("config for Gelf Logger empty") return nil, fmt.Errorf("config can not be empty") } - MWConfig = config + if config.GelfEndpoint == "" { + return nil, fmt.Errorf("you must specify a GELF compatibile endpoint") + } + + if config.GelfPort == 0 || config.GelfPort > 65353 { + return nil, fmt.Errorf("you must specify a valid port") + } + if config.HostnameOverride == "" { - GelfHostname, _ = os.Hostname() + tLog.GelfHostname, _ = os.Hostname() + } else { + tLog.GelfHostname = config.HostnameOverride } - GelfWriter, _ = gelf.NewUDPWriter(fmt.Sprintf("%s:%d", config.GelfEndpoint, config.GelfPort)) + tLog.GelfWriter, _ = gelf.NewUDPWriter(fmt.Sprintf("%s:%d", config.GelfEndpoint, config.GelfPort)) return tLog, nil } func (h *GelfLog) ServeHTTP(rw http.ResponseWriter, req *http.Request) { id := betterguid.New() - if MWConfig.EmitRequestStart { - req.Header.Set(MWConfig.RequestStartTimeHeader, fmt.Sprint(makeTimestampMilli())) + if h.Config.EmitRequestStart { + req.Header.Set(h.Config.RequestStartTimeHeader, fmt.Sprint(makeTimestampMilli())) } - if MWConfig.EmitTraceId { - req.Header.Set(MWConfig.TraceIdHeader, fmt.Sprint(id)) + if h.Config.EmitTraceId { + req.Header.Set(h.Config.TraceIdHeader, fmt.Sprint(id)) } - if GelfWriter != nil { + if h.GelfWriter != nil { var headerMap = map[string]interface{}{} for str, val := range req.Header { - headerMap[str] = val + for index, iVal := range val { + headerName := str + if index > 0 { + headerName = fmt.Sprintf("%s_%d", str, index) + } + headerMap[headerName] = iVal + } } headerMap["Host"] = req.Host - message := wrapMessage(fmt.Sprintf("Request to %s", req.Host), fmt.Sprintf("Request to %s", req.Host), 5, headerMap) - e := GelfWriter.WriteMessage(message) - - if e != nil { - log.Println("Received error when sending GELF message:", e.Error()) - } + message := wrapMessage(fmt.Sprintf("Request to %s", req.Host), fmt.Sprintf("Request to %s", req.Host), h.GelfHostname, headerMap) + h.GelfWriter.WriteMessage(message) } h.Next.ServeHTTP(rw, req) } - -func wrapMessage(s string, f string, l int32, ex map[string]interface{}) *gelf.Message { +func wrapMessage(s string, f string, h string, ex map[string]interface{}) *gelf.Message { /* - Level is a stanard syslog level + Level is a standard syslog level Facility is deprecated Line is deprecated File is deprecated @@ -96,11 +103,11 @@ func wrapMessage(s string, f string, l int32, ex map[string]interface{}) *gelf.M m := &gelf.Message{ Version: "1.1", - Host: GelfHostname, + Host: h, Short: s, Full: f, TimeUnix: float64(time.Now().Unix()), - Level: l, + Level: 5, Extra: ex, } diff --git a/gelflog_test.go b/gelflog_test.go new file mode 100644 index 0000000..f46d1ab --- /dev/null +++ b/gelflog_test.go @@ -0,0 +1,102 @@ +package traefik_gelf_plugin + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +type httpHandlerMock struct{} + +func (h *httpHandlerMock) ServeHTTP(http.ResponseWriter, *http.Request) {} + +func TestGoodConfig(t *testing.T) { + config := CreateConfig() + config.GelfEndpoint = "192.168.2.4" + config.GelfPort = 12203 + g, err := New(nil, &httpHandlerMock{}, config, "GelfLogger") + + if err != nil { + t.Fatal(err) + } + + + req := httptest.NewRequest(http.MethodGet, "http://localhost/some/path", nil) + req.RemoteAddr = "4.0.0.0:34000" + rw := httptest.NewRecorder() + + g.ServeHTTP(rw, req) + + if config.EmitTraceId { + traceHeader := req.Header.Get(config.TraceIdHeader) + if traceHeader == "" { + t.Fatal("trace id empty") + } + } + + if config.EmitRequestStart { + reqStartHeader := req.Header.Get(config.RequestStartTimeHeader) + if reqStartHeader == "" { + t.Fatal("request start empty") + } + } +} +func TestHostnameOverride(t *testing.T) { + config := CreateConfig() + config.GelfEndpoint = "192.168.2.4" + config.GelfPort = 12203 + config.HostnameOverride = "avimac01.av.local" + g, err := New(nil, &httpHandlerMock{}, config, "GelfLogger") + + if err != nil { + t.Fatal(err) + } + + + req := httptest.NewRequest(http.MethodGet, "http://localhost/some/path", nil) + req.RemoteAddr = "4.0.0.0:34000" + req.Header.Add("X-Test-Redundant", "abc") + req.Header.Add("X-Test-Redundant", "123") + rw := httptest.NewRecorder() + + g.ServeHTTP(rw, req) + + if config.EmitTraceId { + traceHeader := req.Header.Get(config.TraceIdHeader) + if traceHeader == "" { + t.Fatal("trace id empty") + } + } + + if config.EmitRequestStart { + reqStartHeader := req.Header.Get(config.RequestStartTimeHeader) + if reqStartHeader == "" { + t.Fatal("request start empty") + } + } +} +func TestBadConfig(t *testing.T) { + config := CreateConfig() + + g, err := New(nil, &httpHandlerMock{}, config, "GelfLogger") + + if g != nil { + t.Fatal(err) + } + +} +func TestMissingPort(t *testing.T) { + config := CreateConfig() + config.GelfEndpoint = "192.168.2.4" + g, err := New(nil, &httpHandlerMock{}, config, "GelfLogger") + + if g != nil { + t.Fatal(err) + } +} +func TestMissingConfig(t *testing.T) { + g, err := New(nil, &httpHandlerMock{}, nil, "GelfLogger") + if g != nil { + t.Fatal(err) + } +} \ No newline at end of file diff --git a/go.mod b/go.mod index ab0eee6..ea78e86 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/itninja04/traefik-gelf-plugin -go 1.14 +go 1.16 require ( github.com/kjk/betterguid v0.0.0-20170621091430-c442874ba63a diff --git a/go.sum b/go.sum index 4fd633f..90d3f60 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ -github.com/Graylog2/go-gelf v0.0.0-20170811154226-7ebf4f536d8f h1:xMWj7GzE4gCkm8e+661/GJHDXr4h7/jt4kM1Vvr9c5k= -github.com/Graylog2/go-gelf v0.0.0-20170811154226-7ebf4f536d8f/go.mod h1:fBaQWrftOD5CrVCUfoYGHs4X4VViTuGOXA8WloCjTY0= github.com/kjk/betterguid v0.0.0-20170621091430-c442874ba63a h1:b+Gt8sQs//Sl5Dcem5zP9Qc2FgEUAygREa2AAa2Vmcw= github.com/kjk/betterguid v0.0.0-20170621091430-c442874ba63a/go.mod h1:uxRAhHE1nl34DpWgfe0CYbNYbCnYplaB6rZH9ReWtUk= +github.com/traefik/yaegi v0.9.15 h1:8AboQQiXe7iSVWnrzxFmUUx9FZj1x+ekXPt/UVLrqS4= +github.com/traefik/yaegi v0.9.15/go.mod h1:FAYnRlZyuVlEkvnkHq3bvJ1lW5be6XuwgLdkYgYG6Lk= gopkg.in/Graylog2/go-gelf.v2 v2.0.0-20191017102106-1550ee647df0 h1:Xg23ydYYJLmb9AK3XdcEpplHZd1MpN3X2ZeeMoBClmY= gopkg.in/Graylog2/go-gelf.v2 v2.0.0-20191017102106-1550ee647df0/go.mod h1:CeDeqW4tj9FrgZXF/dQCWZrBdcZWWBenhJtxLH4On2g= diff --git a/vendor/modules.txt b/vendor/modules.txt index 97af476..2537167 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1,5 +1,3 @@ -# github.com/Graylog2/go-gelf v0.0.0-20170811154226-7ebf4f536d8f -## explicit # github.com/kjk/betterguid v0.0.0-20170621091430-c442874ba63a ## explicit github.com/kjk/betterguid