From adb1ad3c6d485a227f4568b4e83e641e706eae94 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 23 Nov 2022 15:52:19 +0100 Subject: [PATCH] Fix code formatting --- cmd/eosio-api-healtcheck/main.go | 260 +++++++++++---------- internal/api/debug.go | 48 ++-- internal/api/debug_test.go | 44 ++-- internal/api/eosio_contract.go | 111 +++++---- internal/api/eosio_contract_test.go | 252 ++++++++++---------- internal/api/eosio_v1.go | 84 ++++--- internal/api/eosio_v1_test.go | 190 +++++++-------- internal/api/eosio_v2.go | 112 +++++---- internal/api/eosio_v2_test.go | 235 +++++++++---------- internal/api/interface.go | 20 +- internal/api/log_params.go | 5 +- internal/api/log_params_test.go | 65 +++--- internal/parse_request.go | 80 ++++--- internal/parse_request_test.go | 109 ++++----- internal/server.go | 68 +++--- internal/utils/json.go | 13 +- internal/utils/json_test.go | 32 +-- internal/utils/parse_log_formatter.go | 24 +- internal/utils/parse_log_formatter_test.go | 42 ++-- internal/utils/time.go | 16 +- internal/utils/time_test.go | 24 +- 21 files changed, 884 insertions(+), 950 deletions(-) diff --git a/cmd/eosio-api-healtcheck/main.go b/cmd/eosio-api-healtcheck/main.go index 7a96702..7852282 100644 --- a/cmd/eosio-api-healtcheck/main.go +++ b/cmd/eosio-api-healtcheck/main.go @@ -1,22 +1,25 @@ package main import ( - "fmt" - "os" - "os/signal" - "syscall" - "github.com/eosswedenorg/eosio-api-healthcheck/internal" - "github.com/eosswedenorg/eosio-api-healthcheck/internal/utils" - log "github.com/inconshreveable/log15" - "github.com/eosswedenorg-go/pid" - "github.com/pborman/getopt/v2" + "fmt" + "os" + "os/signal" + "syscall" + + "github.com/eosswedenorg-go/pid" + "github.com/eosswedenorg/eosio-api-healthcheck/internal" + "github.com/eosswedenorg/eosio-api-healthcheck/internal/utils" + log "github.com/inconshreveable/log15" + "github.com/pborman/getopt/v2" ) // Command line flags // --------------------------------------------------------- -var logFile string -var pidFile string +var ( + logFile string + pidFile string +) // Global variables // --------------------------------------------------------- @@ -28,159 +31,160 @@ var VersionString string = "-" // File descriptor to the current log file. var logfd *os.File -var logfmt log.Format -var logger log.Logger +var ( + logfmt log.Format + logger log.Logger +) -// argv_listen_addr -// Parse listen address from command line. +// argv_listen_addr +// Parse listen address from command line. +// // --------------------------------------------------------- func argv_listen_addr() string { + var addr string - var addr string + argv := getopt.Args() + if len(argv) > 0 { + addr = argv[0] + } else { + addr = "127.0.0.1" + } - argv := getopt.Args() - if len(argv) > 0 { - addr = argv[0] - } else { - addr = "127.0.0.1" - } + addr += ":" + if len(argv) > 1 { + addr += argv[1] + } else { + addr += "1337" + } - addr += ":" - if len(argv) > 1 { - addr += argv[1] - } else { - addr += "1337" - } - - return addr + return addr } func setLogFile() { + // Open file + fd, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0o644) + if err != nil { + logger.Error(err.Error()) + } - // Open file - fd, err := os.OpenFile(logFile, os.O_APPEND | os.O_CREATE | os.O_WRONLY, 0644) - if err != nil { - logger.Error(err.Error()) - } + // Try close if old descriptor is defined. + if logfd != nil { + if err = logfd.Close(); err != nil { + logger.Error(err.Error()) + } + } - // Try close if old descriptor is defined. - if logfd != nil { - if err = logfd.Close(); err != nil { - logger.Error(err.Error()) - } - } - - // Update variable and set log writer. - logfd = fd - logger.SetHandler(log.StreamHandler(logfd, logfmt)) + // Update variable and set log writer. + logfd = fd + logger.SetHandler(log.StreamHandler(logfd, logfmt)) } -// signalEventLoop() -// Initialize event channel for OS signals -// and runs an event loop. +// signalEventLoop() +// Initialize event channel for OS signals +// and runs an event loop. +// // --------------------------------------------------------- func signalEventLoop() { + // Setup a channel + sig_ch := make(chan os.Signal, 1) - // Setup a channel - sig_ch := make(chan os.Signal, 1) + // subscribe to SIGHUP signal. + signal.Notify(sig_ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) - // subscribe to SIGHUP signal. - signal.Notify(sig_ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM) + // Event loop + func() { + var run bool = true + for run { + // Block until we get a signal. + sig := <-sig_ch - // Event loop - func() { - var run bool = true - for run { - // Block until we get a signal. - sig := <- sig_ch + l := logger.New("signal", sig) - l := logger.New("signal", sig) + switch sig { + case syscall.SIGINT, syscall.SIGTERM: + l.Info("Program was asked to terminate.") + run = false + // SIGHUP is sent when logfile is rotated. + case syscall.SIGHUP: + msg := "Logfile was rotated: " - switch sig { - case syscall.SIGINT, syscall.SIGTERM : - l.Info("Program was asked to terminate.") - run = false - // SIGHUP is sent when logfile is rotated. - case syscall.SIGHUP : - msg := "Logfile was rotated: " + if logfd != nil { + setLogFile() + msg += "Filedescriptor was updated" + } else { + msg += "No Filedescriptor to update (most likely uses standard out/err streams)" + } - if logfd != nil { - setLogFile() - msg += "Filedescriptor was updated" - } else { - msg += "No Filedescriptor to update (most likely uses standard out/err streams)" - } - - l.Info(msg) - default: - l.Warn("Unknown signal") - } - } - }() + l.Info(msg) + default: + l.Warn("Unknown signal") + } + } + }() } -// main +// main +// // --------------------------------------------------------- func main() { + var version bool + var usage bool + var addr string + var logFormatter *string - var version bool - var usage bool - var addr string - var logFormatter *string + logger = log.Root() - logger = log.Root() + // Command line parsing + getopt.SetParameters("[ip] [port]") + getopt.FlagLong(&usage, "help", 'h', "Print this help text") + getopt.FlagLong(&version, "version", 'v', "Print version") + getopt.FlagLong(&logFile, "log", 'l', "Path to log file", "file") + getopt.FlagLong(&pidFile, "pid", 'p', "Path to pid file", "file") + logFormatter = getopt.EnumLong("log-format", 0, []string{"term", "logfmt", "json", "json-pretty"}, "", "Log format to use: term,logfmt,json,json-pretty") - // Command line parsing - getopt.SetParameters("[ip] [port]") - getopt.FlagLong(&usage, "help", 'h', "Print this help text") - getopt.FlagLong(&version, "version", 'v', "Print version") - getopt.FlagLong(&logFile, "log", 'l', "Path to log file", "file") - getopt.FlagLong(&pidFile, "pid", 'p', "Path to pid file", "file") - logFormatter = getopt.EnumLong("log-format", 0, []string{"term", "logfmt", "json", "json-pretty"}, "", "Log format to use: term,logfmt,json,json-pretty") + getopt.Parse() - getopt.Parse() + if usage { + getopt.Usage() + return + } - if usage { - getopt.Usage() - return - } + if version { + fmt.Printf("Version: %s\n", VersionString) + return + } - if version { - fmt.Printf("Version: %s\n", VersionString) - return; - } + logfmt = utils.ParseLogFormatter(*logFormatter) - logfmt = utils.ParseLogFormatter(*logFormatter) + // Open logfile. + if len(logFile) > 0 { + setLogFile() + } else { + logger.SetHandler(log.StreamHandler(os.Stdout, logfmt)) + } - // Open logfile. - if len(logFile) > 0 { - setLogFile() - } else { - logger.SetHandler(log.StreamHandler(os.Stdout, logfmt)) - } + logger.Info("Process is starting", "pid", pid.Get()) - logger.Info("Process is starting", "pid", pid.Get()) + if len(pidFile) > 0 { + logger.Info("Writing pidfile", "file", pidFile) + err := pid.Save(pidFile) + if err != nil { + logger.Error("Failed to write pidfile", "msg", err) + } + } - if len(pidFile) > 0 { - logger.Info("Writing pidfile", "file", pidFile) - err := pid.Save(pidFile) - if err != nil { - logger.Error("Failed to write pidfile", "msg", err) - } - } + addr = argv_listen_addr() - addr = argv_listen_addr() + // Start listening to TCP Connections + err := internal.SpawnTcpServer(addr) + if err == nil { + logger.Info("TCP Server started", "addr", addr) - // Start listening to TCP Connections - err := internal.SpawnTcpServer(addr) - if err == nil { - logger.Info("TCP Server started", "addr", addr) + // Run the signal event loop. + signalEventLoop() + } else { + log.Error("Failed to start tcp server", "error", err) + } - // Run the signal event loop. - signalEventLoop() - } else { - log.Error("Failed to start tcp server", "error", err) - } - - logger.Info("Shutdown") + logger.Info("Shutdown") } diff --git a/internal/api/debug.go b/internal/api/debug.go index a9fa905..a9480dd 100644 --- a/internal/api/debug.go +++ b/internal/api/debug.go @@ -1,50 +1,48 @@ - package api import ( - "strings" - "github.com/eosswedenorg-go/haproxy/agentcheck" + "strings" + + "github.com/eosswedenorg-go/haproxy/agentcheck" ) type DebugApi struct { - response agentcheck.Response + response agentcheck.Response } func parseResponse(resp string) (agentcheck.Response, error) { + parts := strings.SplitN(resp, "#", 2) - parts := strings.SplitN(resp, "#", 2) + // Status with message + if len(parts) > 1 { + rtype := agentcheck.StatusMessageResponseType(parts[0]) + return agentcheck.NewStatusMessageResponse(rtype, parts[1]), nil + } - // Status with message - if len(parts) > 1 { - rtype := agentcheck.StatusMessageResponseType(parts[0]) - return agentcheck.NewStatusMessageResponse(rtype, parts[1]), nil - } - - // Only status. - rtype := agentcheck.StatusResponseType(parts[0]) - return agentcheck.NewStatusResponse(rtype), nil + // Only status. + rtype := agentcheck.StatusResponseType(parts[0]) + return agentcheck.NewStatusResponse(rtype), nil } func DebugApiFactory(args ApiArguments) ApiInterface { - return NewDebugApi(args.Url) + return NewDebugApi(args.Url) } func NewDebugApi(response string) DebugApi { + resp, _ := parseResponse(response) - resp, _ := parseResponse(response) - - return DebugApi{ - response: resp, - } + return DebugApi{ + response: resp, + } } func (d DebugApi) LogInfo() LogParams { - return LogParams{ - "type", "Debug", - "response", strings.TrimSpace(d.response.String()), - } + return LogParams{ + "type", "Debug", + "response", strings.TrimSpace(d.response.String()), + } } func (d DebugApi) Call() (agentcheck.Response, string) { - return d.response, "" + return d.response, "" } diff --git a/internal/api/debug_test.go b/internal/api/debug_test.go index d262cf3..9768120 100644 --- a/internal/api/debug_test.go +++ b/internal/api/debug_test.go @@ -3,20 +3,20 @@ package api import ( "reflect" "testing" - "github.com/stretchr/testify/assert" + "github.com/eosswedenorg-go/haproxy/agentcheck" + "github.com/stretchr/testify/assert" ) func TestDebugApiFactory(t *testing.T) { + api := DebugApiFactory(ApiArguments{ + Url: "up", + Host: "host", + NumBlocks: 40, + }) - api := DebugApiFactory(ApiArguments{ - Url: "up", - Host: "host", - NumBlocks: 40, - }) - - assert.IsType(t, DebugApi{}, api) - assert.Equal(t, api.(DebugApi).response, agentcheck.NewStatusResponse(agentcheck.Up)) + assert.IsType(t, DebugApi{}, api) + assert.Equal(t, api.(DebugApi).response, agentcheck.NewStatusResponse(agentcheck.Up)) } func TestNewDebugApi(t *testing.T) { @@ -43,26 +43,24 @@ func TestNewDebugApi(t *testing.T) { } func TestDebugApi_LogInfo(t *testing.T) { + expected := LogParams{"type", "Debug", "response", "up"} - expected := LogParams{"type", "Debug", "response", "up"} + api := DebugApi{ + response: agentcheck.NewStatusResponse(agentcheck.Up), + } - api := DebugApi{ - response: agentcheck.NewStatusResponse(agentcheck.Up), - } - - assert.Equal(t, api.LogInfo(), expected) + assert.Equal(t, api.LogInfo(), expected) } func TestDebugApi_Call(t *testing.T) { + expected := agentcheck.NewStatusMessageResponse(agentcheck.Stopped, "message") - expected := agentcheck.NewStatusMessageResponse(agentcheck.Stopped, "message") + api := DebugApi{ + response: expected, + } - api := DebugApi{ - response: expected, - } + response, msg := api.Call() - response, msg := api.Call() - - assert.Equal(t, response, expected) - assert.Equal(t, msg, "") + assert.Equal(t, response, expected) + assert.Equal(t, msg, "") } diff --git a/internal/api/eosio_contract.go b/internal/api/eosio_contract.go index 748d092..58d41a3 100644 --- a/internal/api/eosio_contract.go +++ b/internal/api/eosio_contract.go @@ -1,81 +1,80 @@ - package api import ( - "fmt" - "github.com/eosswedenorg/eosio-api-healthcheck/internal/utils" - "github.com/eosswedenorg-go/haproxy/agentcheck" - contract_api "github.com/eosswedenorg-go/eos-contract-api-client" + "fmt" + + contract_api "github.com/eosswedenorg-go/eos-contract-api-client" + "github.com/eosswedenorg-go/haproxy/agentcheck" + "github.com/eosswedenorg/eosio-api-healthcheck/internal/utils" ) type EosioContract struct { - utils.Time - client contract_api.Client - block_time float64 + utils.Time + client contract_api.Client + block_time float64 } func EosioContractFactory(args ApiArguments) ApiInterface { - return NewEosioContract(args.Url, float64(args.NumBlocks / 2)) + return NewEosioContract(args.Url, float64(args.NumBlocks/2)) } func NewEosioContract(url string, block_time float64) EosioContract { - return EosioContract{ - client: contract_api.Client{ - Url: url, - }, - block_time: block_time, - } + return EosioContract{ + client: contract_api.Client{ + Url: url, + }, + block_time: block_time, + } } func (e EosioContract) LogInfo() LogParams { - return LogParams{ - "type", "eosio-contract", - "url", e.client.Url, - "block_time", e.block_time, - } + return LogParams{ + "type", "eosio-contract", + "url", e.client.Url, + "block_time", e.block_time, + } } func (e EosioContract) Call() (agentcheck.Response, string) { + h, err := e.client.GetHealth() + if err != nil { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + return resp, err.Error() + } - h, err := e.client.GetHealth() - if err != nil { - resp := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - return resp, err.Error() - } + // Check HTTP Status Code + if h.HTTPStatusCode > 299 { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + msg := "Taking offline because %v was received from backend" + return resp, fmt.Sprintf(msg, h.HTTPStatusCode) + } - // Check HTTP Status Code - if h.HTTPStatusCode > 299 { - resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - msg := "Taking offline because %v was received from backend" - return resp, fmt.Sprintf(msg, h.HTTPStatusCode) - } + // Check postgres + if h.Data.Postgres.Status != "OK" { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + msg := "Taking offline because Postgres reported '%s'" + return resp, fmt.Sprintf(msg, h.Data.Postgres.Status) + } - // Check postgres - if h.Data.Postgres.Status != "OK" { - resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - msg := "Taking offline because Postgres reported '%s'" - return resp, fmt.Sprintf(msg, h.Data.Postgres.Status) - } + // Check redis + if h.Data.Redis.Status != "OK" { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + msg := "Taking offline because Redis reported '%s'" + return resp, fmt.Sprintf(msg, h.Data.Redis.Status) + } - // Check redis - if h.Data.Redis.Status != "OK" { - resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - msg := "Taking offline because Redis reported '%s'" - return resp, fmt.Sprintf(msg, h.Data.Redis.Status) - } + // Validate head block. + diff := e.GetTime().Sub(h.Data.Chain.HeadTime).Seconds() - // Validate head block. - diff := e.GetTime().Sub(h.Data.Chain.HeadTime).Seconds() + if diff > e.block_time { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + msg := "Taking offline because head block is lagging %.0f seconds" + return resp, fmt.Sprintf(msg, diff) + } else if diff < -e.block_time { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + msg := "Taking offline because head block is %.0f seconds into the future" + return resp, fmt.Sprintf(msg, diff) + } - if diff > e.block_time { - resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - msg := "Taking offline because head block is lagging %.0f seconds" - return resp, fmt.Sprintf(msg, diff) - } else if diff < -e.block_time { - resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - msg := "Taking offline because head block is %.0f seconds into the future" - return resp, fmt.Sprintf(msg, diff) - } - - return agentcheck.NewStatusResponse(agentcheck.Up), "OK" + return agentcheck.NewStatusResponse(agentcheck.Up), "OK" } diff --git a/internal/api/eosio_contract_test.go b/internal/api/eosio_contract_test.go index 9c1520f..0bd86e8 100644 --- a/internal/api/eosio_contract_test.go +++ b/internal/api/eosio_contract_test.go @@ -1,86 +1,80 @@ - package api import ( - "time" - "testing" - "net/http" - "net/http/httptest" - "github.com/stretchr/testify/assert" - "github.com/eosswedenorg-go/haproxy/agentcheck" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/eosswedenorg-go/haproxy/agentcheck" + "github.com/stretchr/testify/assert" ) func TestEosioContractFactory(t *testing.T) { + api := EosioContractFactory(ApiArguments{ + Url: "https://atomic.example.com", + NumBlocks: 120, + }) - api := EosioContractFactory(ApiArguments{ - Url: "https://atomic.example.com", - NumBlocks: 120, - }) + expected := NewEosioContract("https://atomic.example.com", 60) - expected := NewEosioContract("https://atomic.example.com", 60) - - assert.IsType(t, expected, api) - assert.Equal(t, expected.client.Url, api.(EosioContract).client.Url) - assert.Equal(t, expected.client.Host, api.(EosioContract).client.Host) - assert.Equal(t, expected.block_time, api.(EosioContract).block_time) + assert.IsType(t, expected, api) + assert.Equal(t, expected.client.Url, api.(EosioContract).client.Url) + assert.Equal(t, expected.client.Host, api.(EosioContract).client.Host) + assert.Equal(t, expected.block_time, api.(EosioContract).block_time) } func TestEosioContractLogInfo(t *testing.T) { + api := NewEosioContract("https://atomic.example.com", 120) - api := NewEosioContract("https://atomic.example.com", 120) + expected := LogParams{"type", "eosio-contract", "url", "https://atomic.example.com", "block_time", float64(120)} - expected := LogParams{"type","eosio-contract","url","https://atomic.example.com","block_time",float64(120)} - - assert.Equal(t, expected, api.LogInfo()) + assert.Equal(t, expected, api.LogInfo()) } func TestEosioContractSetTime(t *testing.T) { + expected := time.Date(2019, 3, 18, 20, 29, 32, 0, time.UTC) - expected := time.Date(2019, 3, 18, 20, 29, 32, 0, time.UTC) + api := NewEosioContract("", 60) + // Assert that time is NOW (+-10 seconds) + assert.InDelta(t, api.GetTime().Unix(), time.Now().In(time.UTC).Unix(), float64(10)) - api := NewEosioContract("", 60) - // Assert that time is NOW (+-10 seconds) - assert.InDelta(t, api.GetTime().Unix(), time.Now().In(time.UTC).Unix(), float64(10)) - - api.SetTime(expected) - assert.Equal(t, expected, api.GetTime()) + api.SetTime(expected) + assert.Equal(t, expected, api.GetTime()) } func TestEosioContractJsonFailure(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res.Write([]byte(`!//{invalid-json}!##`)) + })) - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - res.Write([]byte(`!//{invalid-json}!##`)) - })) + api := NewEosioContract(srv.URL, 120) + check, _ := api.Call() - api := NewEosioContract(srv.URL, 120) - check, _ := api.Call() - - expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + assert.Equal(t, expected, check) } func TestEosioContractHTTP500Down(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res.Header().Add("Content-type", "application/json; charset=utf-8") + res.WriteHeader(500) + res.Write([]byte(`{}`)) + })) - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - res.Header().Add("Content-type", "application/json; charset=utf-8") - res.WriteHeader(500) - res.Write([]byte(`{}`)) - })) + api := NewEosioContract(srv.URL, 120) + check, status := api.Call() - api := NewEosioContract(srv.URL, 120) - check, status := api.Call() + assert.Equal(t, "Taking offline because 500 was received from backend", status) - assert.Equal(t, "Taking offline because 500 was received from backend", status) - - expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + assert.Equal(t, expected, check) } func TestEosioContractLaggingUp(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/health" { - payload := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/health" { + payload := `{ "success":true, "data":{ "version":"1.0.0", @@ -99,27 +93,26 @@ func TestEosioContractLaggingUp(t *testing.T) { "query_time":1759953929542 }` - res.Header().Add("Content-type", "application/json; charset=utf-8") - res.Write([]byte(payload)) - } - })) + res.Header().Add("Content-type", "application/json; charset=utf-8") + res.Write([]byte(payload)) + } + })) - api := NewEosioContract(srv.URL, 120) - api.SetTime(time.Date(2025, 10, 8, 20, 7, 27, 0, time.UTC)) + api := NewEosioContract(srv.URL, 120) + api.SetTime(time.Date(2025, 10, 8, 20, 7, 27, 0, time.UTC)) - check, status := api.Call() + check, status := api.Call() - assert.Equal(t, "OK", status) + assert.Equal(t, "OK", status) - expected := agentcheck.NewStatusResponse(agentcheck.Up) - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusResponse(agentcheck.Up) + assert.Equal(t, expected, check) } func TestEosioContractLaggingDown(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/health" { - payload := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/health" { + payload := `{ "success":true, "data":{ "version":"1.0.0", @@ -138,27 +131,26 @@ func TestEosioContractLaggingDown(t *testing.T) { "query_time":1533451895542 }` - res.Header().Add("Content-type", "application/json; charset=utf-8") - res.Write([]byte(payload)) - } - })) + res.Header().Add("Content-type", "application/json; charset=utf-8") + res.Write([]byte(payload)) + } + })) - api := NewEosioContract(srv.URL, 120) - api.SetTime(time.Date(2018, 8, 5, 6, 53, 35, 0, time.UTC)) + api := NewEosioContract(srv.URL, 120) + api.SetTime(time.Date(2018, 8, 5, 6, 53, 35, 0, time.UTC)) - check, status := api.Call() + check, status := api.Call() - assert.Equal(t, "Taking offline because head block is lagging 121 seconds", status) + assert.Equal(t, "Taking offline because head block is lagging 121 seconds", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + assert.Equal(t, expected, check) } func TestEosioContractInFutureUp(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/health" { - payload := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/health" { + payload := `{ "success":true, "data":{ "version":"1.0.0", @@ -177,27 +169,26 @@ func TestEosioContractInFutureUp(t *testing.T) { "query_time":1728954678231 }` - res.Header().Add("Content-type", "application/json; charset=utf-8") - res.Write([]byte(payload)) - } - })) + res.Header().Add("Content-type", "application/json; charset=utf-8") + res.Write([]byte(payload)) + } + })) - api := NewEosioContract(srv.URL, 120) - api.SetTime(time.Date(2024, 10, 15, 1, 9, 16, 500, time.UTC)) + api := NewEosioContract(srv.URL, 120) + api.SetTime(time.Date(2024, 10, 15, 1, 9, 16, 500, time.UTC)) - check, status := api.Call() + check, status := api.Call() - assert.Equal(t, "OK", status) + assert.Equal(t, "OK", status) - expected := agentcheck.NewStatusResponse(agentcheck.Up) - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusResponse(agentcheck.Up) + assert.Equal(t, expected, check) } func TestEosioContractInFutureDown(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/health" { - payload := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/health" { + payload := `{ "success":true, "data":{ "version":"1.0.0", @@ -216,28 +207,26 @@ func TestEosioContractInFutureDown(t *testing.T) { "query_time":1041122832231 }` - res.Header().Add("Content-type", "application/json; charset=utf-8") - res.Write([]byte(payload)) - } - })) + res.Header().Add("Content-type", "application/json; charset=utf-8") + res.Write([]byte(payload)) + } + })) - api := NewEosioContract(srv.URL, 120) - api.SetTime(time.Date(2002, 12, 29, 0, 45, 03, 500, time.UTC)) + api := NewEosioContract(srv.URL, 120) + api.SetTime(time.Date(2002, 12, 29, 0, 45, 0o3, 500, time.UTC)) - check, status := api.Call() + check, status := api.Call() - assert.Equal(t, "Taking offline because head block is -121 seconds into the future", status) + assert.Equal(t, "Taking offline because head block is -121 seconds into the future", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + assert.Equal(t, expected, check) } - func TestEosioContractRedisDown(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/health" { - payload := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/health" { + payload := `{ "success":true, "data":{ "version":"1.0.0", @@ -256,27 +245,26 @@ func TestEosioContractRedisDown(t *testing.T) { "query_time":1426072775872 }` - res.Header().Add("Content-type", "application/json; charset=utf-8") - res.Write([]byte(payload)) - } - })) + res.Header().Add("Content-type", "application/json; charset=utf-8") + res.Write([]byte(payload)) + } + })) - api := NewEosioContract(srv.URL, 120) - api.SetTime(time.Date(2015, 3, 11, 11, 19, 30, 500, time.UTC)) + api := NewEosioContract(srv.URL, 120) + api.SetTime(time.Date(2015, 3, 11, 11, 19, 30, 500, time.UTC)) - check, status := api.Call() + check, status := api.Call() - assert.Equal(t, "Taking offline because Redis reported 'DOWN'", status) + assert.Equal(t, "Taking offline because Redis reported 'DOWN'", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + assert.Equal(t, expected, check) } func TestEosioContractPostgresDown(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/health" { - payload := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/health" { + payload := `{ "success":true, "data":{ "version":"1.0.0", @@ -295,18 +283,18 @@ func TestEosioContractPostgresDown(t *testing.T) { "query_time":156286837143 }` - res.Header().Add("Content-type", "application/json; charset=utf-8") - res.Write([]byte(payload)) - } - })) + res.Header().Add("Content-type", "application/json; charset=utf-8") + res.Write([]byte(payload)) + } + })) - api := NewEosioContract(srv.URL, 120) - api.SetTime(time.Date(2019, 7, 11, 18, 6, 11, 500, time.UTC)) + api := NewEosioContract(srv.URL, 120) + api.SetTime(time.Date(2019, 7, 11, 18, 6, 11, 500, time.UTC)) - check, status := api.Call() + check, status := api.Call() - assert.Equal(t, "Taking offline because Postgres reported 'DOWN'", status) + assert.Equal(t, "Taking offline because Postgres reported 'DOWN'", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + assert.Equal(t, expected, check) } diff --git a/internal/api/eosio_v1.go b/internal/api/eosio_v1.go index 8d0bf87..5c13a18 100644 --- a/internal/api/eosio_v1.go +++ b/internal/api/eosio_v1.go @@ -1,73 +1,71 @@ - package api import ( - "fmt" - "github.com/eosswedenorg/eosio-api-healthcheck/internal/utils" - "github.com/eosswedenorg-go/haproxy/agentcheck" - "github.com/eosswedenorg-go/eosapi" + "fmt" + + "github.com/eosswedenorg-go/eosapi" + "github.com/eosswedenorg-go/haproxy/agentcheck" + "github.com/eosswedenorg/eosio-api-healthcheck/internal/utils" ) type EosioV1 struct { - utils.Time - client eosapi.Client - block_time float64 + utils.Time + client eosapi.Client + block_time float64 } func EosioV1Factory(args ApiArguments) ApiInterface { - return NewEosioV1(args.Url, args.Host, float64(args.NumBlocks / 2)) + return NewEosioV1(args.Url, args.Host, float64(args.NumBlocks/2)) } func NewEosioV1(url string, host string, block_time float64) EosioV1 { + api := EosioV1{ + client: *eosapi.New(url), + block_time: block_time, + } - api := EosioV1{ - client: *eosapi.New(url), - block_time: block_time, - } + api.client.Host = host - api.client.Host = host - - return api + return api } func (e EosioV1) LogInfo() LogParams { - p := LogParams{ - "type", "eosio-v1", - "url", e.client.Url, - } + p := LogParams{ + "type", "eosio-v1", + "url", e.client.Url, + } - if len(e.client.Host) > 0 { - p.Add("host", e.client.Host) - } + if len(e.client.Host) > 0 { + p.Add("host", e.client.Host) + } - p.Add("block_time", e.block_time) + p.Add("block_time", e.block_time) - return p + return p } func (e EosioV1) Call() (agentcheck.Response, string) { + info, err := e.client.GetInfo() + if err != nil { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + return resp, err.Error() + } - info, err := e.client.GetInfo() - if err != nil { - resp := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - return resp, err.Error() - } + // Validate head block. + diff := e.GetTime().Sub(info.HeadBlockTime).Seconds() - // Validate head block. - diff := e.GetTime().Sub(info.HeadBlockTime).Seconds() + if diff > e.block_time { - if diff > e.block_time { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + msg := "Taking offline because head block is lagging %.0f seconds" + return resp, fmt.Sprintf(msg, diff) + } else if diff < -e.block_time { - msg := "Taking offline because head block is lagging %.0f seconds" - return resp, fmt.Sprintf(msg, diff) - } else if diff < -e.block_time { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - - msg := "Taking offline because head block is %.0f seconds into the future" - return resp, fmt.Sprintf(msg, diff) - } - return agentcheck.NewStatusResponse(agentcheck.Up), "OK" + msg := "Taking offline because head block is %.0f seconds into the future" + return resp, fmt.Sprintf(msg, diff) + } + return agentcheck.NewStatusResponse(agentcheck.Up), "OK" } diff --git a/internal/api/eosio_v1_test.go b/internal/api/eosio_v1_test.go index 2b2f4ea..da98e7b 100644 --- a/internal/api/eosio_v1_test.go +++ b/internal/api/eosio_v1_test.go @@ -1,174 +1,164 @@ - package api import ( - "time" - "testing" - "net/http" - "net/http/httptest" - "github.com/stretchr/testify/assert" - "github.com/eosswedenorg-go/haproxy/agentcheck" + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/eosswedenorg-go/haproxy/agentcheck" + "github.com/stretchr/testify/assert" ) func TestEosioV1Factory(t *testing.T) { + api := EosioV1Factory(ApiArguments{ + Url: "https://api.v1.example.com", + Host: "host.example.com", + NumBlocks: 120, + }) - api := EosioV1Factory(ApiArguments{ - Url: "https://api.v1.example.com", - Host: "host.example.com", - NumBlocks: 120, - }) + expected := NewEosioV1("https://api.v1.example.com", "host.example.com", 60) - expected := NewEosioV1("https://api.v1.example.com", "host.example.com", 60) - - assert.IsType(t, expected, api) - assert.Equal(t, expected.client.Url, api.(EosioV1).client.Url) - assert.Equal(t, expected.client.Host, api.(EosioV1).client.Host) - assert.Equal(t, expected.block_time, api.(EosioV1).block_time) + assert.IsType(t, expected, api) + assert.Equal(t, expected.client.Url, api.(EosioV1).client.Url) + assert.Equal(t, expected.client.Host, api.(EosioV1).client.Host) + assert.Equal(t, expected.block_time, api.(EosioV1).block_time) } func TestEosioV1LogInfo(t *testing.T) { + api := NewEosioV1("https://api.v1.example.com", "host.example.com", 120) - api := NewEosioV1("https://api.v1.example.com", "host.example.com", 120) + expected := LogParams{"type", "eosio-v1", "url", "https://api.v1.example.com", "host", "host.example.com", "block_time", float64(120)} - expected := LogParams{"type","eosio-v1","url","https://api.v1.example.com","host","host.example.com","block_time",float64(120)} - - assert.Equal(t, expected, api.LogInfo()) + assert.Equal(t, expected, api.LogInfo()) } func TestEosioV1SetTime(t *testing.T) { + expected := time.Date(2022, 2, 24, 13, 38, 0, 0, time.UTC) - expected := time.Date(2022, 2, 24, 13, 38, 0, 0, time.UTC) + api := NewEosioV1("", "", 60) + // Assert that time is NOW (+-10 seconds) + assert.InDelta(t, api.GetTime().Unix(), time.Now().In(time.UTC).Unix(), float64(10)) - api := NewEosioV1("", "", 60) - // Assert that time is NOW (+-10 seconds) - assert.InDelta(t, api.GetTime().Unix(), time.Now().In(time.UTC).Unix(), float64(10)) - - api.SetTime(expected) - assert.Equal(t, expected, api.GetTime()) + api.SetTime(expected) + assert.Equal(t, expected, api.GetTime()) } func TestEosioV1JsonFailure(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res.Write([]byte(`!//{invalid-json}!##`)) + })) - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - res.Write([]byte(`!//{invalid-json}!##`)) - })) + api := NewEosioV1(srv.URL, "", 120) + check, _ := api.Call() - api := NewEosioV1(srv.URL, "", 120) - check, _ := api.Call() - - expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + assert.Equal(t, expected, check) } func TestEosioV1HTTP500Failed(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res.WriteHeader(500) + res.Write([]byte(`{}`)) + })) - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - res.WriteHeader(500) - res.Write([]byte(`{}`)) - })) + api := NewEosioV1(srv.URL, "", 120) + check, status := api.Call() - api := NewEosioV1(srv.URL, "", 120) - check, status := api.Call() + assert.Equal(t, "server returned HTTP 500 Internal Server Error", status) - assert.Equal(t, "server returned HTTP 500 Internal Server Error", status) - - expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + assert.Equal(t, expected, check) } func TestEosioV1LaggingUp(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v1/chain/get_info" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v1/chain/get_info" { + info := `{ "server_version": "8f613ec9", "head_block_num": 7272812, "head_block_time": "2022-02-24T13:37:00" }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV1(srv.URL, "", 60) - api.SetTime(time.Date(2022, 2, 24, 13, 38, 0, 0, time.UTC)) - check, status := api.Call() + api := NewEosioV1(srv.URL, "", 60) + api.SetTime(time.Date(2022, 2, 24, 13, 38, 0, 0, time.UTC)) + check, status := api.Call() - assert.Equal(t, "OK", status) + assert.Equal(t, "OK", status) - expected := agentcheck.NewStatusResponse(agentcheck.Up) - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusResponse(agentcheck.Up) + assert.Equal(t, expected, check) } func TestEosioV1LaggingDown(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v1/chain/get_info" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v1/chain/get_info" { + info := `{ "server_version": "9a607cce", "head_block_num": 87263, "head_block_time": "2018-01-01T13:37:01" }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV1(srv.URL, "", 60) - api.SetTime(time.Date(2018, time.January, 1, 13, 38, 2, 0, time.UTC)) - check, status := api.Call() + api := NewEosioV1(srv.URL, "", 60) + api.SetTime(time.Date(2018, time.January, 1, 13, 38, 2, 0, time.UTC)) + check, status := api.Call() - assert.Equal(t, "Taking offline because head block is lagging 61 seconds", status) + assert.Equal(t, "Taking offline because head block is lagging 61 seconds", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + assert.Equal(t, expected, check) } func TestEosioV1TimeInFutureUP(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v1/chain/get_info" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v1/chain/get_info" { + info := `{ "server_version": "d1bec8d3", "head_block_num": 548847, "head_block_time": "2020-09-22T09:32:00" }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV1(srv.URL, "", 120) - api.SetTime(time.Date(2020, 9, 22, 9, 30, 0, 0, time.UTC)) - check, status := api.Call() + api := NewEosioV1(srv.URL, "", 120) + api.SetTime(time.Date(2020, 9, 22, 9, 30, 0, 0, time.UTC)) + check, status := api.Call() - assert.Equal(t, "OK", status) + assert.Equal(t, "OK", status) - expected := agentcheck.NewStatusResponse(agentcheck.Up) - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusResponse(agentcheck.Up) + assert.Equal(t, expected, check) } - func TestEosioV1TimeInFutureDown(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v1/chain/get_info" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v1/chain/get_info" { + info := `{ "server_version": "c879d231", "head_block_num": 2637621, "head_block_time": "2019-04-14T12:02:01" }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV1(srv.URL, "", 120) - api.SetTime(time.Date(2019, time.April, 14, 12, 0, 0, 0, time.UTC)) - check, status := api.Call() + api := NewEosioV1(srv.URL, "", 120) + api.SetTime(time.Date(2019, time.April, 14, 12, 0, 0, 0, time.UTC)) + check, status := api.Call() - assert.Equal(t, "Taking offline because head block is -121 seconds into the future", status) + assert.Equal(t, "Taking offline because head block is -121 seconds into the future", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + assert.Equal(t, expected, check) } diff --git a/internal/api/eosio_v2.go b/internal/api/eosio_v2.go index b0d838f..58cdd65 100644 --- a/internal/api/eosio_v2.go +++ b/internal/api/eosio_v2.go @@ -1,86 +1,84 @@ - package api import ( - "fmt" - "github.com/eosswedenorg/eosio-api-healthcheck/internal/utils" - "github.com/eosswedenorg-go/haproxy/agentcheck" - "github.com/eosswedenorg-go/eosapi" + "fmt" + + "github.com/eosswedenorg-go/eosapi" + "github.com/eosswedenorg-go/haproxy/agentcheck" + "github.com/eosswedenorg/eosio-api-healthcheck/internal/utils" ) type EosioV2 struct { - client eosapi.Client - offset int64 + client eosapi.Client + offset int64 } func EosioV2Factory(args ApiArguments) ApiInterface { - return NewEosioV2(args.Url, args.Host, int64(args.NumBlocks)) + return NewEosioV2(args.Url, args.Host, int64(args.NumBlocks)) } func NewEosioV2(url string, host string, offset int64) EosioV2 { + api := EosioV2{ + client: *eosapi.New(url), + offset: offset, + } - api := EosioV2{ - client: *eosapi.New(url), - offset: offset, - } + api.client.Host = host - api.client.Host = host - - return api + return api } func (e EosioV2) LogInfo() LogParams { - p := LogParams{ - "type", "eosio-v2", - "url", e.client.Url, - } + p := LogParams{ + "type", "eosio-v2", + "url", e.client.Url, + } - if len(e.client.Host) > 0 { - p.Add("host", e.client.Host) - } + if len(e.client.Host) > 0 { + p.Add("host", e.client.Host) + } - p.Add("offset", e.offset) + p.Add("offset", e.offset) - return p + return p } func (e EosioV2) Call() (agentcheck.Response, string) { + health, err := e.client.GetHealth() + if err != nil { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + return resp, err.Error() + } - health, err := e.client.GetHealth() - if err != nil { - resp := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - return resp, err.Error() - } + // Fetch elasticsearch and nodeos block numbers from json. + var es_block int64 = 0 + var node_block int64 = 0 - // Fetch elasticsearch and nodeos block numbers from json. - var es_block int64 = 0 - var node_block int64 = 0 + for _, v := range health.Health { + if v.Name == "Elasticsearch" { + es_block = utils.JsonGetInt64(v.Data["last_indexed_block"]) + } else if v.Name == "NodeosRPC" { + node_block = utils.JsonGetInt64(v.Data["head_block_num"]) + } + } - for _, v := range health.Health { - if v.Name == "Elasticsearch" { - es_block = utils.JsonGetInt64(v.Data["last_indexed_block"]) - } else if v.Name == "NodeosRPC" { - node_block = utils.JsonGetInt64(v.Data["head_block_num"]) - } - } + // Error out if ether or both are zero. + if es_block == 0 || node_block == 0 { + msg := fmt.Sprintf("Failed to get Elasticsearch and/or nodeos "+ + "block numbers (es: %d, eos: %d)", es_block, node_block) - // Error out if ether or both are zero. - if es_block == 0 || node_block == 0 { - msg := fmt.Sprintf("Failed to get Elasticsearch and/or nodeos " + - "block numbers (es: %d, eos: %d)", es_block, node_block) + resp := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + return resp, msg + } - resp := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - return resp, msg - } - - // Check if ES is behind or in the future. - diff := node_block - es_block; - if diff > e.offset { - resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - return resp, fmt.Sprintf("Taking offline because Elastic is %d blocks behind", diff) - } else if diff < -e.offset { - resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - return resp, fmt.Sprintf("Taking offline because Elastic is %d blocks into the future", -1 * diff) - } - return agentcheck.NewStatusResponse(agentcheck.Up), "OK" + // Check if ES is behind or in the future. + diff := node_block - es_block + if diff > e.offset { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + return resp, fmt.Sprintf("Taking offline because Elastic is %d blocks behind", diff) + } else if diff < -e.offset { + resp := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + return resp, fmt.Sprintf("Taking offline because Elastic is %d blocks into the future", -1*diff) + } + return agentcheck.NewStatusResponse(agentcheck.Up), "OK" } diff --git a/internal/api/eosio_v2_test.go b/internal/api/eosio_v2_test.go index 116589b..0241511 100644 --- a/internal/api/eosio_v2_test.go +++ b/internal/api/eosio_v2_test.go @@ -1,73 +1,68 @@ - package api import ( - "testing" - "net/http" - "net/http/httptest" - "github.com/stretchr/testify/assert" - "github.com/eosswedenorg-go/haproxy/agentcheck" + "net/http" + "net/http/httptest" + "testing" + + "github.com/eosswedenorg-go/haproxy/agentcheck" + "github.com/stretchr/testify/assert" ) func TestEosioV2Factory(t *testing.T) { + api := EosioV2Factory(ApiArguments{ + Url: "https://api.v2.example.com", + Host: "host.example.com", + NumBlocks: 120, + }) - api := EosioV2Factory(ApiArguments{ - Url: "https://api.v2.example.com", - Host: "host.example.com", - NumBlocks: 120, - }) + expected := NewEosioV2("https://api.v2.example.com", "host.example.com", 120) - expected := NewEosioV2("https://api.v2.example.com", "host.example.com", 120) - - assert.IsType(t, expected, api) - assert.Equal(t, expected.client.Url, api.(EosioV2).client.Url) - assert.Equal(t, expected.client.Host, api.(EosioV2).client.Host) - assert.Equal(t, expected.offset, api.(EosioV2).offset) + assert.IsType(t, expected, api) + assert.Equal(t, expected.client.Url, api.(EosioV2).client.Url) + assert.Equal(t, expected.client.Host, api.(EosioV2).client.Host) + assert.Equal(t, expected.offset, api.(EosioV2).offset) } func TestEosioV2LogInfo(t *testing.T) { + api := NewEosioV2("https://api.v2.example.com", "host.example.com", 120) - api := NewEosioV2("https://api.v2.example.com", "host.example.com", 120) + expected := LogParams{"type", "eosio-v2", "url", "https://api.v2.example.com", "host", "host.example.com", "offset", int64(120)} - expected := LogParams{"type","eosio-v2","url","https://api.v2.example.com","host","host.example.com","offset",int64(120)} - - assert.Equal(t, expected, api.LogInfo()) + assert.Equal(t, expected, api.LogInfo()) } func TestEosioV2JsonFailure(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res.Write([]byte(`!//{invalid-json}!##`)) + })) - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - res.Write([]byte(`!//{invalid-json}!##`)) - })) + api := NewEosioV2(srv.URL, "", 120) + check, _ := api.Call() - api := NewEosioV2(srv.URL, "", 120) - check, _ := api.Call() - - expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + assert.Equal(t, expected, check) } func TestEosioV2HTTP500Failed(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + res.WriteHeader(500) + res.Write([]byte(`{}`)) + })) - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - res.WriteHeader(500) - res.Write([]byte(`{}`)) - })) + api := NewEosioV2(srv.URL, "", 120) + check, status := api.Call() - api := NewEosioV2(srv.URL, "", 120) - check, status := api.Call() + assert.Equal(t, "server returned HTTP 500 Internal Server Error", status) - assert.Equal(t, "server returned HTTP 500 Internal Server Error", status) - - expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + assert.Equal(t, expected, check) } func TestEosioV2LaggingUp(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v2/health" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v2/health" { + info := `{ "version": "1.0", "version_hash": "028d5a34463884fcbe2ecfd3c0fcb3b5d4d538f4fd64803c1ef7209c85f2f266", "host": "api.test.com:443", @@ -97,24 +92,23 @@ func TestEosioV2LaggingUp(t *testing.T) { ] }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV2(srv.URL, "", 500) - check, status := api.Call() + api := NewEosioV2(srv.URL, "", 500) + check, status := api.Call() - assert.Equal(t, "OK", status) + assert.Equal(t, "OK", status) - expected := agentcheck.NewStatusResponse(agentcheck.Up) - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusResponse(agentcheck.Up) + assert.Equal(t, expected, check) } func TestEosioV2LaggingDown(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v2/health" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v2/health" { + info := `{ "version": "1.0", "version_hash": "028d5a34463884fcbe2ecfd3c0fcb3b5d4d538f4fd64803c1ef7209c85f2f266", "host": "api.test.com:443", @@ -144,24 +138,23 @@ func TestEosioV2LaggingDown(t *testing.T) { ] }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV2(srv.URL, "", 499) - check, status := api.Call() + api := NewEosioV2(srv.URL, "", 499) + check, status := api.Call() - assert.Equal(t, "Taking offline because Elastic is 500 blocks behind", status) + assert.Equal(t, "Taking offline because Elastic is 500 blocks behind", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + assert.Equal(t, expected, check) } func TestEosioV2LaggingESInFutureUP(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v2/health" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v2/health" { + info := `{ "version": "1.0", "version_hash": "028d5a34463884fcbe2ecfd3c0fcb3b5d4d538f4fd64803c1ef7209c85f2f266", "host": "api.test.com:443", @@ -191,24 +184,23 @@ func TestEosioV2LaggingESInFutureUP(t *testing.T) { ] }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV2(srv.URL, "", 200) - check, status := api.Call() + api := NewEosioV2(srv.URL, "", 200) + check, status := api.Call() - assert.Equal(t, "OK", status) + assert.Equal(t, "OK", status) - expected := agentcheck.NewStatusResponse(agentcheck.Up) - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusResponse(agentcheck.Up) + assert.Equal(t, expected, check) } func TestEosioV2LaggingESInFutureDown(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v2/health" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v2/health" { + info := `{ "version": "1.0", "version_hash": "028d5a34463884fcbe2ecfd3c0fcb3b5d4d538f4fd64803c1ef7209c85f2f266", "host": "api.test.com:443", @@ -238,24 +230,23 @@ func TestEosioV2LaggingESInFutureDown(t *testing.T) { ] }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV2(srv.URL, "", 200) - check, status := api.Call() + api := NewEosioV2(srv.URL, "", 200) + check, status := api.Call() - assert.Equal(t, "Taking offline because Elastic is 201 blocks into the future", status) + assert.Equal(t, "Taking offline because Elastic is 201 blocks into the future", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Down, "") + assert.Equal(t, expected, check) } func TestEosioV2ElasticsFailed(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v2/health" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v2/health" { + info := `{ "version": "1.0", "version_hash": "028d5a34463884fcbe2ecfd3c0fcb3b5d4d538f4fd64803c1ef7209c85f2f266", "host": "api.test.com:443", @@ -285,24 +276,23 @@ func TestEosioV2ElasticsFailed(t *testing.T) { ] }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV2(srv.URL, "", 500) - check, status := api.Call() + api := NewEosioV2(srv.URL, "", 500) + check, status := api.Call() - assert.Equal(t, "Failed to get Elasticsearch and/or nodeos block numbers (es: 0, eos: 263148621)", status) + assert.Equal(t, "Failed to get Elasticsearch and/or nodeos block numbers (es: 0, eos: 263148621)", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + assert.Equal(t, expected, check) } func TestEosioV2NodeosRPCFailed(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v2/health" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v2/health" { + info := `{ "version": "1.0", "version_hash": "028d5a34463884fcbe2ecfd3c0fcb3b5d4d538f4fd64803c1ef7209c85f2f266", "host": "api.test.com:443", @@ -332,24 +322,23 @@ func TestEosioV2NodeosRPCFailed(t *testing.T) { ] }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV2(srv.URL, "", 500) - check, status := api.Call() + api := NewEosioV2(srv.URL, "", 500) + check, status := api.Call() - assert.Equal(t, "Failed to get Elasticsearch and/or nodeos block numbers (es: 263148121, eos: 0)", status) + assert.Equal(t, "Failed to get Elasticsearch and/or nodeos block numbers (es: 263148121, eos: 0)", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + assert.Equal(t, expected, check) } func TestEosioV2ElasticsNodeosRPCFailed(t *testing.T) { - - var srv = httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { - if req.URL.String() == "/v2/health" { - info := `{ + srv := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) { + if req.URL.String() == "/v2/health" { + info := `{ "version": "1.0", "version_hash": "028d5a34463884fcbe2ecfd3c0fcb3b5d4d538f4fd64803c1ef7209c85f2f266", "host": "api.test.com:443", @@ -369,15 +358,15 @@ func TestEosioV2ElasticsNodeosRPCFailed(t *testing.T) { ] }` - res.Write([]byte(info)) - } - })) + res.Write([]byte(info)) + } + })) - api := NewEosioV2(srv.URL, "", 500) - check, status := api.Call() + api := NewEosioV2(srv.URL, "", 500) + check, status := api.Call() - assert.Equal(t, "Failed to get Elasticsearch and/or nodeos block numbers (es: 0, eos: 0)", status) + assert.Equal(t, "Failed to get Elasticsearch and/or nodeos block numbers (es: 0, eos: 0)", status) - expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - assert.Equal(t, expected, check) + expected := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + assert.Equal(t, expected, check) } diff --git a/internal/api/interface.go b/internal/api/interface.go index dcb5760..9bbf438 100644 --- a/internal/api/interface.go +++ b/internal/api/interface.go @@ -1,8 +1,7 @@ - package api import ( - "github.com/eosswedenorg-go/haproxy/agentcheck" + "github.com/eosswedenorg-go/haproxy/agentcheck" ) /** @@ -10,9 +9,9 @@ import ( * to configure the API request. */ type ApiArguments struct { - Url string - Host string - NumBlocks int + Url string + Host string + NumBlocks int } /** @@ -20,14 +19,13 @@ type ApiArguments struct { * * Each API must implement this function and process `args` * returing a instance of it's implementation of the ApiInterface -*/ + */ type Factory func(args ApiArguments) ApiInterface type ApiInterface interface { + // Returns Logging information + LogInfo() LogParams - // Returns Logging information - LogInfo() LogParams - - // Call api and validate it's status. - Call() (agentcheck.Response, string) + // Call api and validate it's status. + Call() (agentcheck.Response, string) } diff --git a/internal/api/log_params.go b/internal/api/log_params.go index 01961fa..0b00337 100644 --- a/internal/api/log_params.go +++ b/internal/api/log_params.go @@ -1,14 +1,13 @@ - package api type LogParams []interface{} func (p *LogParams) Add(field string, value interface{}) { - *p = append(*p, field, value) + *p = append(*p, field, value) } // Syntactic sugar for append(p, other...) // Returns a new instance of LogParams with all values from both p and other func (p LogParams) Combine(other LogParams) LogParams { - return append(p, other...) + return append(p, other...) } diff --git a/internal/api/log_params_test.go b/internal/api/log_params_test.go index dc91cbf..5002bbd 100644 --- a/internal/api/log_params_test.go +++ b/internal/api/log_params_test.go @@ -1,50 +1,47 @@ - package api import ( - "testing" - "github.com/stretchr/testify/assert" + "testing" + + "github.com/stretchr/testify/assert" ) - - func TestLogParams(t *testing.T) { + type test_struct struct { + First string + Second int + } - type test_struct struct { - First string - Second int - } + p := LogParams{} - p := LogParams{} + p.Add("one", 1) + p.Add("string", "str") + p.Add("struct", test_struct{First: "first_string", Second: 1234}) - p.Add("one", 1) - p.Add("string", "str") - p.Add("struct", test_struct{First:"first_string",Second:1234}) + expected := []interface{}([]interface{}{ + "one", 1, + "string", "str", + "struct", + test_struct{ + First: "first_string", + Second: 1234, + }, + }) - expected := []interface{}([]interface {}{ - "one",1, - "string","str", - "struct",test_struct{ - First:"first_string", - Second:1234, - }, - }) - - assert.ElementsMatch(t, expected, p) + assert.ElementsMatch(t, expected, p) } func TestLogParamsCombine(t *testing.T) { + a := LogParams{"one", 1, "string1", "str1"} - a := LogParams{"one",1,"string1","str1"} + b := LogParams{"two", 2, "string2", "str2"} - b := LogParams{"two",2,"string2","str2"} + expected := LogParams{ + "one", 1, + "string1", "str1", + "two", 2, + "string2", "str2", + } - expected := LogParams{ - "one",1, - "string1","str1", - "two",2, - "string2","str2", - } - - assert.Equal(t, expected, a.Combine(b)) -} \ No newline at end of file + assert.Equal(t, expected, a.Combine(b)) +} diff --git a/internal/parse_request.go b/internal/parse_request.go index bc1a49e..fbcfac7 100644 --- a/internal/parse_request.go +++ b/internal/parse_request.go @@ -1,60 +1,58 @@ - package internal import ( - "strings" - "fmt" - "strconv" - "github.com/eosswedenorg/eosio-api-healthcheck/internal/api" + "fmt" + "strconv" + "strings" + + "github.com/eosswedenorg/eosio-api-healthcheck/internal/api" ) func ParseArguments(args []string) api.ApiArguments { + a := api.ApiArguments{ + NumBlocks: 10, + } - a := api.ApiArguments{ - NumBlocks: 10, - } + // 1. url (scheme + ip/domain + port) + a.Url = args[0] - // 1. url (scheme + ip/domain + port) - a.Url = args[0] + // 2. num blocks + if len(args) > 1 { + num, err := strconv.ParseInt(args[1], 10, 32) + if err == nil { + a.NumBlocks = int(num) + } + } - // 2. num blocks - if len(args) > 1 { - num, err := strconv.ParseInt(args[1], 10, 32) - if err == nil { - a.NumBlocks = int(num) - } - } + // 3. Host + if len(args) > 2 { + a.Host = args[2] + } - // 3. Host - if len(args) > 2 { - a.Host = args[2] - } - - return a + return a } func ParseRequest(request string) (api.ApiInterface, error) { + factories := map[string]api.Factory{ + "v1": api.EosioV1Factory, + "v2": api.EosioV2Factory, + "contract": api.EosioContractFactory, + "debug": api.DebugApiFactory, + } - factories := map[string]api.Factory{ - "v1": api.EosioV1Factory, - "v2": api.EosioV2Factory, - "contract": api.EosioContractFactory, - "debug": api.DebugApiFactory, - } + // Parse arguments. + // ------------------- + p := strings.Split(strings.TrimSpace(request), "|") - // Parse arguments. - // ------------------- - p := strings.Split(strings.TrimSpace(request), "|") + if len(p) < 2 { + return nil, fmt.Errorf("invalid number of parameters in agent request") + } - if len(p) < 2 { - return nil, fmt.Errorf("invalid number of parameters in agent request") - } + a := ParseArguments(p[1:]) - a := ParseArguments(p[1:]) + if factory, ok := factories[p[0]]; ok { + return factory(a), nil + } - if factory, ok := factories[p[0]]; ok { - return factory(a), nil - } - - return nil, fmt.Errorf("invalid API '%s'", p[0]) + return nil, fmt.Errorf("invalid API '%s'", p[0]) } diff --git a/internal/parse_request_test.go b/internal/parse_request_test.go index b7691ec..3fdefb7 100644 --- a/internal/parse_request_test.go +++ b/internal/parse_request_test.go @@ -1,117 +1,104 @@ - package internal import ( - // "fmt" - "testing" - "github.com/stretchr/testify/assert" - "github.com/eosswedenorg/eosio-api-healthcheck/internal/api" + "testing" + // "fmt" + "github.com/eosswedenorg/eosio-api-healthcheck/internal/api" + "github.com/stretchr/testify/assert" ) func TestParseWithInvalidApi(t *testing.T) { - - api, err := ParseRequest("invalid|http://api.example.com") - assert.Error(t, err) - assert.Equal(t, err.Error(), "invalid API 'invalid'") - assert.Nil(t, api) + api, err := ParseRequest("invalid|http://api.example.com") + assert.Error(t, err) + assert.Equal(t, err.Error(), "invalid API 'invalid'") + assert.Nil(t, api) } func TestParseWithInvalidParams(t *testing.T) { - - api, err := ParseRequest("v1") - assert.Error(t, err) - assert.Equal(t, err.Error(), "invalid number of parameters in agent request") - assert.Nil(t, api) + api, err := ParseRequest("v1") + assert.Error(t, err) + assert.Equal(t, err.Error(), "invalid number of parameters in agent request") + assert.Nil(t, api) } // EosioV1 // -------------------------------- func TestParseEosioV1(t *testing.T) { + expected := api.NewEosioV1("http://api.example.com", "", 5) - expected := api.NewEosioV1("http://api.example.com", "", 5) - - api, err := ParseRequest("v1|http://api.example.com") - assert.NoError(t, err) - assert.Equal(t, expected.LogInfo(), api.LogInfo()) + api, err := ParseRequest("v1|http://api.example.com") + assert.NoError(t, err) + assert.Equal(t, expected.LogInfo(), api.LogInfo()) } func TestParseEosioV1WithBlockNumber(t *testing.T) { + expected := api.NewEosioV1("http://api.example.com", "", 1000) - expected := api.NewEosioV1("http://api.example.com", "", 1000) - - api, err := ParseRequest("v1|http://api.example.com|2000") - assert.NoError(t, err) - assert.Equal(t, expected.LogInfo(), api.LogInfo()) + api, err := ParseRequest("v1|http://api.example.com|2000") + assert.NoError(t, err) + assert.Equal(t, expected.LogInfo(), api.LogInfo()) } - func TestParseEosioV1Full(t *testing.T) { + expected := api.NewEosioV1("http://api.example.com", "http://host.example.com", 500) - expected := api.NewEosioV1("http://api.example.com", "http://host.example.com", 500) - - api, err := ParseRequest("v1|http://api.example.com|1000|http://host.example.com") - assert.NoError(t, err) - assert.Equal(t, expected.LogInfo(), api.LogInfo()) + api, err := ParseRequest("v1|http://api.example.com|1000|http://host.example.com") + assert.NoError(t, err) + assert.Equal(t, expected.LogInfo(), api.LogInfo()) } // EosioV2 // -------------------------------- func TestParseEosioV2(t *testing.T) { + expected := api.NewEosioV2("http://api.v2.example.com", "", 10) - expected := api.NewEosioV2("http://api.v2.example.com", "", 10) - - api, err := ParseRequest("v2|http://api.v2.example.com") - assert.NoError(t, err) - assert.Equal(t, expected.LogInfo(), api.LogInfo()) + api, err := ParseRequest("v2|http://api.v2.example.com") + assert.NoError(t, err) + assert.Equal(t, expected.LogInfo(), api.LogInfo()) } func TestParseEosioV2WithOffset(t *testing.T) { + expected := api.NewEosioV2("http://api.v2.example.com", "", 1000) - expected := api.NewEosioV2("http://api.v2.example.com", "", 1000) - - api, err := ParseRequest("v2|http://api.v2.example.com|1000") - assert.NoError(t, err) - assert.Equal(t, expected.LogInfo(), api.LogInfo()) + api, err := ParseRequest("v2|http://api.v2.example.com|1000") + assert.NoError(t, err) + assert.Equal(t, expected.LogInfo(), api.LogInfo()) } func TestParseEosioV2Full(t *testing.T) { + expected := api.NewEosioV2("http://api.v2.example.com", "http://host.example.com", 1000) - expected := api.NewEosioV2("http://api.v2.example.com", "http://host.example.com", 1000) + api, err := ParseRequest("v2|http://api.v2.example.com|1000|http://host.example.com") + assert.NoError(t, err) - api, err := ParseRequest("v2|http://api.v2.example.com|1000|http://host.example.com") - assert.NoError(t, err) - - assert.Equal(t, expected.LogInfo(), api.LogInfo()) + assert.Equal(t, expected.LogInfo(), api.LogInfo()) } // EosioContract // -------------------------------- func TestParseEosioContract(t *testing.T) { + expected := api.NewEosioContract("http://api.contract.example.com", 5) - expected := api.NewEosioContract("http://api.contract.example.com", 5) - - api, err := ParseRequest("contract|http://api.contract.example.com") - assert.NoError(t, err) - assert.Equal(t, expected.LogInfo(), api.LogInfo()) + api, err := ParseRequest("contract|http://api.contract.example.com") + assert.NoError(t, err) + assert.Equal(t, expected.LogInfo(), api.LogInfo()) } func TestParseEosioContractWithBlockTime(t *testing.T) { + expected := api.NewEosioContract("http://api.contract.example.com", 256) - expected := api.NewEosioContract("http://api.contract.example.com", 256) - - api, err := ParseRequest("contract|http://api.contract.example.com|512") - assert.NoError(t, err) - assert.Equal(t, expected.LogInfo(), api.LogInfo()) + api, err := ParseRequest("contract|http://api.contract.example.com|512") + assert.NoError(t, err) + assert.Equal(t, expected.LogInfo(), api.LogInfo()) } func TestParseDebugApi(t *testing.T) { + expected := api.NewDebugApi("some_api_call") - expected := api.NewDebugApi("some_api_call") - - api, err := ParseRequest("debug|some_api_call") - assert.NoError(t, err) - assert.Equal(t, expected.LogInfo(), api.LogInfo()) + api, err := ParseRequest("debug|some_api_call") + assert.NoError(t, err) + assert.Equal(t, expected.LogInfo(), api.LogInfo()) } diff --git a/internal/server.go b/internal/server.go index df4081d..6ffaad5 100644 --- a/internal/server.go +++ b/internal/server.go @@ -1,57 +1,57 @@ package internal import ( - "strings" - log "github.com/inconshreveable/log15" - "github.com/eosswedenorg/eosio-api-healthcheck/internal/api" - "github.com/eosswedenorg-go/haproxy/agentcheck" - "github.com/eosswedenorg-go/tcp_server" + "strings" + + "github.com/eosswedenorg-go/haproxy/agentcheck" + "github.com/eosswedenorg-go/tcp_server" + "github.com/eosswedenorg/eosio-api-healthcheck/internal/api" + log "github.com/inconshreveable/log15" ) // onTcpMessage callback function // --------------------------------------------------------- func onTcpMessage(c *tcp_server.Client, args string) { + logger := log.Root() - logger := log.Root() + // Check api. + // ------------------- + healthCheckApi, err := ParseRequest(args) + if err != nil { + logger.Warn("Agent request error", "message", err) + resp := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") - // Check api. - // ------------------- - healthCheckApi, err := ParseRequest(args) - if err != nil { - logger.Warn("Agent request error", "message", err) - resp := agentcheck.NewStatusMessageResponse(agentcheck.Failed, "") + c.WriteString(resp.String()) + c.Close() + return + } - c.WriteString(resp.String()) - c.Close() - return - } + status, msg := healthCheckApi.Call() - status, msg := healthCheckApi.Call() + params := api.LogParams{} + params.Add("status", strings.TrimSpace(status.String())) - params := api.LogParams{} - params.Add("status", strings.TrimSpace(status.String())) + if msg != "OK" && len(msg) > 0 { + params.Add("error", msg) + } - if msg != "OK" && len(msg) > 0 { - params.Add("error", msg) - } - - logger.Info("API Check", params.Combine(healthCheckApi.LogInfo())...) - // Report status to HAproxy - c.WriteString(status.String()) - c.Close() + logger.Info("API Check", params.Combine(healthCheckApi.LogInfo())...) + // Report status to HAproxy + c.WriteString(status.String()) + c.Close() } // SpawnTcpServer // --------------------------------------------------------- func SpawnTcpServer(addr string) error { - server := tcp_server.New(addr) - server.OnMessage(onTcpMessage) + server := tcp_server.New(addr) + server.OnMessage(onTcpMessage) - err := server.Connect() - if err == nil { - go server.Listen() - } - return err + err := server.Connect() + if err == nil { + go server.Listen() + } + return err } diff --git a/internal/utils/json.go b/internal/utils/json.go index dc15a87..f256174 100644 --- a/internal/utils/json.go +++ b/internal/utils/json.go @@ -1,4 +1,3 @@ - package utils // JsonGetInt64 @@ -8,10 +7,10 @@ package utils // if the type assertion fails, the function defaults 0 (zero). // --------------------------------------------------------- -func JsonGetInt64(input interface{}) (int64) { - v, res := input.(float64) - if res { - return (int64) (v) - } - return 0 +func JsonGetInt64(input interface{}) int64 { + v, res := input.(float64) + if res { + return (int64)(v) + } + return 0 } diff --git a/internal/utils/json_test.go b/internal/utils/json_test.go index 69f380f..be132f0 100644 --- a/internal/utils/json_test.go +++ b/internal/utils/json_test.go @@ -3,20 +3,20 @@ package utils import "testing" func TestJsonGetInt64(t *testing.T) { - tests := []struct { - name string - input interface{} - want int64 - }{ - {"String", "test", 0 }, - {"Int", 1234, 0 }, - {"Float", float64(1234), 1234 }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := JsonGetInt64(tt.input); got != tt.want { - t.Errorf("JsonGetInt64() = %v, want %v", got, tt.want) - } - }) - } + tests := []struct { + name string + input interface{} + want int64 + }{ + {"String", "test", 0}, + {"Int", 1234, 0}, + {"Float", float64(1234), 1234}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := JsonGetInt64(tt.input); got != tt.want { + t.Errorf("JsonGetInt64() = %v, want %v", got, tt.want) + } + }) + } } diff --git a/internal/utils/parse_log_formatter.go b/internal/utils/parse_log_formatter.go index d655e0b..94b3e49 100644 --- a/internal/utils/parse_log_formatter.go +++ b/internal/utils/parse_log_formatter.go @@ -1,20 +1,18 @@ - package utils import ( - log "github.com/inconshreveable/log15" + log "github.com/inconshreveable/log15" ) func ParseLogFormatter(name string) log.Format { - - switch name { - case "logfmt" : - return log.LogfmtFormat() - case "json" : - return log.JsonFormat() - case "json-pretty" : - return log.JsonFormatEx(true, true) - default : - return log.TerminalFormat() - } + switch name { + case "logfmt": + return log.LogfmtFormat() + case "json": + return log.JsonFormat() + case "json-pretty": + return log.JsonFormatEx(true, true) + default: + return log.TerminalFormat() + } } diff --git a/internal/utils/parse_log_formatter_test.go b/internal/utils/parse_log_formatter_test.go index efe21e4..902cbfe 100644 --- a/internal/utils/parse_log_formatter_test.go +++ b/internal/utils/parse_log_formatter_test.go @@ -1,29 +1,29 @@ package utils import ( - "reflect" - "testing" + "reflect" + "testing" - log "github.com/inconshreveable/log15" + log "github.com/inconshreveable/log15" ) func Test_ParseLogFormatter(t *testing.T) { - tests := []struct { - name string - arg string - want log.Format - }{ - { "Default", "", log.TerminalFormat() }, - { "LogFmt", "logfmt", log.LogfmtFormat() }, - { "Json", "json", log.JsonFormat() }, - { "JsonPretty", "json-pretty", log.JsonFormat() }, - { "Unknown", "unknown", log.TerminalFormat() }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := ParseLogFormatter(tt.arg); reflect.ValueOf(got).Pointer() != reflect.ValueOf(tt.want).Pointer() { - t.Errorf("parseLogFormatter() = %v, want %v", got, tt.want) - } - }) - } + tests := []struct { + name string + arg string + want log.Format + }{ + {"Default", "", log.TerminalFormat()}, + {"LogFmt", "logfmt", log.LogfmtFormat()}, + {"Json", "json", log.JsonFormat()}, + {"JsonPretty", "json-pretty", log.JsonFormat()}, + {"Unknown", "unknown", log.TerminalFormat()}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := ParseLogFormatter(tt.arg); reflect.ValueOf(got).Pointer() != reflect.ValueOf(tt.want).Pointer() { + t.Errorf("parseLogFormatter() = %v, want %v", got, tt.want) + } + }) + } } diff --git a/internal/utils/time.go b/internal/utils/time.go index 699ca72..b37d468 100644 --- a/internal/utils/time.go +++ b/internal/utils/time.go @@ -1,22 +1,20 @@ - package utils import ( - "time" + "time" ) type Time struct { - ts time.Time + ts time.Time } func (t *Time) SetTime(value time.Time) { - t.ts = value + t.ts = value } func (t Time) GetTime() time.Time { - - if ! t.ts.IsZero() { - return t.ts - } - return time.Now().In(time.UTC) + if !t.ts.IsZero() { + return t.ts + } + return time.Now().In(time.UTC) } diff --git a/internal/utils/time_test.go b/internal/utils/time_test.go index d696ca6..07b059e 100644 --- a/internal/utils/time_test.go +++ b/internal/utils/time_test.go @@ -1,26 +1,24 @@ - package utils import ( - "time" - "testing" - "github.com/stretchr/testify/assert" + "testing" + "time" + + "github.com/stretchr/testify/assert" ) func TestTimeGetTimeWithDefaultValue(t *testing.T) { + var ts Time - var ts Time - - // Assert that time is NOW (+-10 seconds) - assert.InDelta(t, ts.GetTime().Unix(), time.Now().In(time.UTC).Unix(), float64(10)) + // Assert that time is NOW (+-10 seconds) + assert.InDelta(t, ts.GetTime().Unix(), time.Now().In(time.UTC).Unix(), float64(10)) } func TestTimeGetTimeWithSetTime(t *testing.T) { + var ts Time - var ts Time + expected := time.Unix(1048722042, 500) + ts.SetTime(expected) - expected := time.Unix(1048722042, 500) - ts.SetTime(expected) - - assert.Equal(t, expected, ts.GetTime()) + assert.Equal(t, expected, ts.GetTime()) }