Skip to content

Commit

Permalink
Added tests and updated ci process
Browse files Browse the repository at this point in the history
  • Loading branch information
lawrencegripper committed May 3, 2018
1 parent 7dca29a commit 70bd82e
Show file tree
Hide file tree
Showing 14 changed files with 234 additions and 30 deletions.
3 changes: 2 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
vendor
vendor
bin
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
sfTraefikWatchdog
traefik-appinsights-watchdog
debug
bin
**/debug.test
13 changes: 3 additions & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# build stage
FROM golang:1.9.2-alpine AS build-env
FROM golang:1.9.2-alpine
ENV GOBIN /go/bin
RUN apk add --update --no-progress openssl git wget bash gcc musl-dev && \
rm -rf /var/cache/apk/* && \
Expand All @@ -15,12 +15,5 @@ RUN dep ensure --vendor-only -v

COPY . /go/src/github.com/lawrencegripper/traefik-appinsights-watchdog/

RUN chmod +x codechecks.sh; sync; ./codechecks.sh

RUN go build -o traefik-appinsights-watchdog -v

# final stage
FROM alpine
WORKDIR /app
COPY --from=build-env /go/src/github.com/lawrencegripper/traefik-appinsights-watchdog/traefik-appinsights-watchdog .
ENTRYPOINT ["./traefik-appinsights-watchdog"]
RUN chmod +x ./codechecks.sh;
RUN chmod +x ./build.sh
1 change: 0 additions & 1 deletion build.ps1

This file was deleted.

11 changes: 9 additions & 2 deletions build.sh
Original file line number Diff line number Diff line change
@@ -1,2 +1,9 @@
#/bin/sh
docker build . -t traefik-appinsights-watchdog
#/bin/bash
set -e
set -o pipefail

./codechecks.sh

echo "Building...."
GOOS=windows go build -o traefik-appinsights-watchdog -o ./bin/traefik-appinsgihts-watchdog.exe
GOOS=windows go build -o traefik-appinsights-watchdog -o ./bin/traefik-appinsgihts-watchdog
2 changes: 2 additions & 0 deletions ci.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
docker build . -t traefik-appinsights-watchdog
docker run -it traefik-appinsights-watchdog
3 changes: 3 additions & 0 deletions ci.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#/bin/sh
docker build . -t traefik-appinsights-watchdog
docker run -it -v $PWD/bin:/go/src/github.com/lawrencegripper/traefik-appinsights-watchdog/bin traefik-appinsights-watchdog bash -f build.sh
6 changes: 3 additions & 3 deletions codechecks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
set -e
set -o pipefail

go test -v ./...

PKGS=$(go list ./... | grep -v '/vendor/')
GOFILES=$(go list -f '{{range $index, $element := .GoFiles}}{{$.Dir}}/{{$element}}{{"\n"}}{{end}}' ./... | grep -v '/vendor/')
echo "----------> Running gofmt"
Expand All @@ -16,6 +18,4 @@ golint -set_exit_status $PKGS
echo "----------> Running simple"
gosimple $PKGS
echo "----------> Running staticcheck"
staticcheck $PKGS
echo "----------> Running go test"
go test -v -cover $PKGS
staticcheck $PKGS
19 changes: 13 additions & 6 deletions health/health.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,33 @@
package health

import (
"context"
"crypto/tls"
"encoding/json"
"fmt"
"github.com/lawrencegripper/traefik-appinsights-watchdog/types"
"io/ioutil"
"net/http"
"time"

"github.com/lawrencegripper/traefik-appinsights-watchdog/types"
)

// StartCheck poll health endpoint
func StartCheck(config types.Configuration, healthChannel chan<- types.StatsEvent) {
func StartCheck(ctx context.Context, config types.Configuration, healthChannel chan<- types.StatsEvent) {
intervalDuration := time.Second * time.Duration(config.PollIntervalSec)
tlsConfig := &tls.Config{}
if config.AllowInvalidCert {
tlsConfig.InsecureSkipVerify = true
}
for {
ev := getStatsEvent(config.TraefikHealthEndpoint, tlsConfig)
healthChannel <- ev
time.Sleep(intervalDuration)
select {
case <-ctx.Done():
return
default:
ev := getStatsEvent(config.TraefikHealthEndpoint, tlsConfig)
healthChannel <- ev
time.Sleep(intervalDuration)
}
}
}

Expand Down Expand Up @@ -60,7 +67,7 @@ func getStatsEvent(endpoint string, tlsConfig *tls.Config) types.StatsEvent {
}
var data map[string]interface{}
jsonErr := json.Unmarshal(body, &data)
if err != nil {
if jsonErr != nil {
event.IsSuccess = false
event.ErrorDetails = jsonErr.Error()
return event
Expand Down
150 changes: 150 additions & 0 deletions health/health_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
package health

import (
"context"
"io/ioutil"
"log"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"

"github.com/lawrencegripper/traefik-appinsights-watchdog/types"
)

func TestHealthRetreiveMetrics(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(handleHealthSuceed))
defer server.Close()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

config := types.Configuration{TraefikHealthEndpoint: server.URL + "/health"}
channel := make(chan types.StatsEvent)

go StartCheck(ctx, config, channel)

timeout := time.After(time.Second * 3)

select {
case statEvent := <-channel:
if !statEvent.IsSuccess {
t.Error("Stats event was a failure")
}
t.Log(statEvent)
return
case <-timeout:
t.Error("Timeout occurred")
return
}
}

func TestHealthRetreiveMetrics_Invalid(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(handleHealthInvalid))
defer server.Close()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

config := types.Configuration{TraefikHealthEndpoint: server.URL + "/health"}
channel := make(chan types.StatsEvent)

go StartCheck(ctx, config, channel)

timeout := time.After(time.Second * 3)

select {
case statEvent := <-channel:
if statEvent.IsSuccess {
t.Error("Stats expected to fail but suceeded")
}
t.Log(statEvent)
return
case <-timeout:
t.Error("Timeout occurred")
return
}
}

func TestHealthRetreiveMetrics_Timeout(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(handleHealthTimeout))
defer server.Close()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()

config := types.Configuration{TraefikHealthEndpoint: server.URL + "/health"}
channel := make(chan types.StatsEvent)

go StartCheck(ctx, config, channel)

timeout := time.After(time.Second * 5)

select {
case statEvent := <-channel:
if statEvent.IsSuccess {
t.Error("Stats expected to fail but suceeded")
}
if !strings.Contains(statEvent.ErrorDetails, "net/http: request canceled (Client.Timeout exceeded while awaiting headers)") {
t.Error("Expected timout error")
}
t.Log(statEvent)
return
case <-timeout:
t.Error("Test timeout occurred")
return
}
}

func handleHealthSuceed(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/health" {
http.NotFound(w, r)
return
}

body, err := ioutil.ReadFile("testdata/healthresponse_normal.json")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, err = w.Write([]byte(err.Error()))
if err != nil {
log.Fatal(err)
}
return
}

w.WriteHeader(http.StatusOK)
_, err = w.Write(body)
if err != nil {
log.Fatal(err)
}
}

func handleHealthInvalid(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/health" {
http.NotFound(w, r)
return
}

body, err := ioutil.ReadFile("testdata/healthresponse_invalid.json")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
_, err = w.Write([]byte(err.Error()))
if err != nil {
log.Fatal(err)
}
return
}

w.WriteHeader(http.StatusOK)
_, err = w.Write(body)
if err != nil {
log.Fatal(err)
}
}

func handleHealthTimeout(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/health" {
http.NotFound(w, r)
return
}

time.Sleep(time.Second * 5)
}
1 change: 1 addition & 0 deletions health/testdata/healthresponse_invalid.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
jammydodgers
31 changes: 31 additions & 0 deletions health/testdata/healthresponse_normal.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"pid": 2458,
"uptime": "39m6.885931127s",
"uptime_sec": 2346.885931127,
"time": "2015-10-07 18:32:24.362238909 +0200 CEST",
"unixtime": 1444235544,
"status_code_count": {
"502": 1
},
"total_status_code_count": {
"200": 7,
"404": 21,
"502": 13
},
"count": 1,
"total_count": 41,
"total_response_time": "35.456865605s",
"total_response_time_sec": 35.456865605,
"average_response_time": "864.8016ms",
"average_response_time_sec": 0.8648016000000001,
"recent_errors": [
{
"status_code": 500,
"status": "Internal Server Error",
"method": "GET",
"host": "localhost",
"path": "/path",
"time": "2016-10-21T16:59:15.418495872-07:00"
}
]
}
6 changes: 4 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"context"
"encoding/json"
"fmt"
"os"
Expand Down Expand Up @@ -60,9 +61,10 @@ func prettyPrintStruct(item interface{}) string {
func startWatchdog(config types.Configuration) {
healthChan := make(chan types.StatsEvent)
client := NewTelemetryClient(config)
ctx := context.Background()

go routing.StartCheck(config, healthChan)
go health.StartCheck(config, healthChan)
go routing.StartCheck(ctx, config, healthChan)
go health.StartCheck(ctx, config, healthChan)

for {
event := <-healthChan
Expand Down
16 changes: 11 additions & 5 deletions routing/routing.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package routing

import (
"context"
"crypto/sha1"
"crypto/tls"
"fmt"
Expand All @@ -15,7 +16,7 @@ import (

// StartCheck begins checking that traefik is routing information successfully by settings up a
// dummy server and pushing requests through traefik back to itself.
func StartCheck(config types.Configuration, healthChannel chan<- types.StatsEvent) {
func StartCheck(ctx context.Context, config types.Configuration, healthChannel chan<- types.StatsEvent) {
context := RequestContext{
Port: config.WatchdogTestServerPort,
FabricURI: config.TraefikBackendName,
Expand All @@ -32,10 +33,15 @@ func StartCheck(config types.Configuration, healthChannel chan<- types.StatsEven
intervalDuration := time.Second * time.Duration(config.PollIntervalSec)
go context.runServer()
for {
context.StartTime = time.Now()
context.Nonce = uuid.New().String()
healthChannel <- context.makeRequest(tlsConfig)
time.Sleep(intervalDuration)
select {
case <-ctx.Done():
return
default:
context.StartTime = time.Now()
context.Nonce = uuid.New().String()
healthChannel <- context.makeRequest(tlsConfig)
time.Sleep(intervalDuration)
}
}
}

Expand Down

0 comments on commit 70bd82e

Please sign in to comment.