diff --git a/ChangeLog.md b/ChangeLog.md index 0491af672e94ce588b79776b6242646c820a6d6e..d472e14f44be6d47391e83dcda422e11b504fa08 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -1,3 +1,9 @@ +* 117 [build] marcin + + Upgraded Go from 1.13.5 to 1.15.5 and golangcilint from 1.21.0 to + 1.33.0. + (Gitlab #457) + * 116 [perf] marcin Improved performance of connecting large Kea installation with many diff --git a/Rakefile b/Rakefile index c7ddca0c3b902c9f70d2f744bbcb73dafe3e5954..1445e90b094ac7cdafc85bca1cf34cf53094961a 100644 --- a/Rakefile +++ b/Rakefile @@ -5,8 +5,8 @@ require 'rake' NODE_VER = '12.16.2' SWAGGER_CODEGEN_VER = '2.4.13' GOSWAGGER_VER = 'v0.23.0' -GOLANGCILINT_VER = '1.21.0' -GO_VER = '1.13.5' +GOLANGCILINT_VER = '1.33.0' +GO_VER = '1.15.5' PROTOC_VER = '3.11.2' PROTOC_GEN_GO_VER = 'v1.3.3' @@ -905,7 +905,7 @@ GECKO_DRV = "#{SELENIUM_DIR}/geckodriver-#{GECKO_DRV_VERSION}" GECKO_DRV_URL = "https://github.com/mozilla/geckodriver/releases/download/v#{GECKO_DRV_VERSION}/geckodriver-v#{GECKO_DRV_VERSION}-linux64.tar.gz" if ENV['CHROME_BIN'] - out = `#{ENV['CHROME_BIN']} --version` + out = `"#{ENV['CHROME_BIN']}" --version` if out.include? '85.' CHROME_DRV_VERSION = '85.0.4183.87' elsif out.include? '86.' diff --git a/backend/.golangci.yml b/backend/.golangci.yml index 7a75bfe91bb7e444d70ab962b4b700a828c0bdfc..a65267359098a07093a50e2602ec620165d93729 100644 --- a/backend/.golangci.yml +++ b/backend/.golangci.yml @@ -1,18 +1,77 @@ linters: - enable-all: true + enable: + - deadcode + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - structcheck + - typecheck + - unused + - varcheck + - asciicheck + - bodyclose + - depguard + - dogsled + - errorlint + - exhaustive + - exportloopref + - gci + - gochecknoglobals + - gochecknoinits + - gocognit + - goconst + - gocritic + - gocyclo + - godot + - goerr113 + - gofmt + - gofumpt + - goheader + - goimports + - golint + - gomodguard + - goprintffuncname + - gosec + - misspell + - nakedret + - nestif + - noctx + - nolintlint + - rowserrcheck + - scopelint + - sqlclosecheck + - stylecheck + - tparallel + - unconvert + - unparam + - whitespace disable: - godox - maligned - lll - funlen - prealloc - - wsl # TODO: reenable later - - interfacer # A tool that suggests interfaces is prone to bad suggestions, so its usefulness in real code is limited. - - dupl # there are some false positives (identical code but operating on different types so no posibility to unify) + - wsl # TODO: reenable later + - interfacer # A tool that suggests interfaces is prone to bad suggestions, so its usefulness in real code is limited. + - dupl # there are some false positives (identical code but operating on different types so no posibility to unify) + - testpackage # Requires rewriting a lot of unit tests and blocks the ability to test unexported functions. + - wrapcheck # We currently use pkg/errors tool that deals with the issue on its own. + - exhaustivestruct # Most of the time you don't want to initialize all fields. + - gomnd # This may be useful but in many cases creating artificial constants, e.g. in tests is counter productive. + - paralleltest # This enforces t.Parallel() usage but some of our tests seem to work incorrectly. Need to fix it first. + - nlreturn # This seems to be overkill and sometimes new lines before continue or break is useless. linters-settings: gocognit: - min-complexity: 40 + min-complexity: 50 + nestif: + min-complexity: 10 + exhaustive: + # Treats switch statements with default case as taking into account all possible cases. + # Without this setting the switch statements must enumerate all possible cases. + default-signifies-exhaustive: true issues: max-same-issues: 3 diff --git a/backend/agent/agent.go b/backend/agent/agent.go index 57887c93a4b7d4211e259481fdd0a20a4b3de917..4fb92c3ca5279d59f560245ce755655231191516 100644 --- a/backend/agent/agent.go +++ b/backend/agent/agent.go @@ -16,7 +16,6 @@ import ( "github.com/shirou/gopsutil/mem" log "github.com/sirupsen/logrus" "google.golang.org/grpc" - "isc.org/stork" agentapi "isc.org/stork/api" ) @@ -27,7 +26,7 @@ type Settings struct { Port int `long:"port" description:"the TCP port to listen on for incoming Stork server connection." default:"8080" env:"STORK_AGENT_PORT"` } -// Global Stork Agent state +// Global Stork Agent state. type StorkAgent struct { Settings Settings AppMonitor AppMonitor diff --git a/backend/agent/agent_test.go b/backend/agent/agent_test.go index ebd89953fcafa65c47745edd730b624a18a6c814..9207ca1eb3b2dea2476675d807f429502126ed68 100644 --- a/backend/agent/agent_test.go +++ b/backend/agent/agent_test.go @@ -12,10 +12,10 @@ import ( "strings" "testing" + "github.com/pkg/errors" log "github.com/sirupsen/logrus" "github.com/stretchr/testify/require" "gopkg.in/h2non/gock.v1" - "isc.org/stork" agentapi "isc.org/stork/api" ) @@ -34,7 +34,7 @@ func mockRndc(command []string) ([]byte, error) { } // unknown command. - output = fmt.Sprintf("unknown command") + output = "unknown command" return []byte(output), nil } @@ -42,7 +42,7 @@ func mockRndc(command []string) ([]byte, error) { func mockRndcError(command []string) ([]byte, error) { log.Debugf("mock rndc: error") - return []byte(""), fmt.Errorf("mocking an error") + return []byte(""), errors.Errorf("mocking an error") } // mockRndcEmpty mocks empty output. @@ -507,7 +507,7 @@ func TestTailTextFile(t *testing.T) { require.Equal(t, "in testing TailTextFile", rsp.Lines[2]) } -// Aux function checks if a list of expected strings is present in the string +// Aux function checks if a list of expected strings is present in the string. func checkOutput(output string, exp []string, reason string) bool { for _, x := range exp { fmt.Printf("Checking if %s exists in %s.\n", x, reason) @@ -521,19 +521,21 @@ func checkOutput(output string, exp []string, reason string) bool { // This is the list of all parameters we expect to be supported by stork-agent. func getExpectedSwitches() []string { - return []string{"-v", "--version", "--listen-prometheus-only", "--listen-stork-only", + return []string{ + "-v", "--version", "--listen-prometheus-only", "--listen-stork-only", "--host", "--port", "--prometheus-kea-exporter-host", "--prometheus-kea-exporter-port", "--prometheus-kea-exporter-interval", "--prometheus-bind9-exporter-host", - "--prometheus-bind9-exporter-port", "--prometheus-bind9-exporter-interval"} + "--prometheus-bind9-exporter-port", "--prometheus-bind9-exporter-interval", + } } -// Location of the stork-agent binary +// Location of the stork-agent binary. const AgentBin = "../cmd/stork-agent/stork-agent" -// Location of the stork-agent man page +// Location of the stork-agent man page. const AgentMan = "../../doc/man/stork-agent.8.rst" -// This test checks if stork-agent -h reports all expected command-line switches +// This test checks if stork-agent -h reports all expected command-line switches. func TestCommandLineSwitches(t *testing.T) { // Run the --help version and get its output. agentCmd := exec.Command(AgentBin, "-h") diff --git a/backend/agent/bind9.go b/backend/agent/bind9.go index ef24f6c8f957fa3af173d58b3ddbca5920003fc9..9d70dd245d26f4fc45e4405347b90492d749a09e 100644 --- a/backend/agent/bind9.go +++ b/backend/agent/bind9.go @@ -8,7 +8,6 @@ import ( "strings" log "github.com/sirupsen/logrus" - storkutil "isc.org/stork/util" ) @@ -25,8 +24,10 @@ type Bind9State struct { Daemon Bind9Daemon } -const RndcDefaultPort = 953 -const StatsChannelDefaultPort = 80 +const ( + RndcDefaultPort = 953 + StatsChannelDefaultPort = 80 +) const defaultNamedConfFile = "/etc/bind/named.conf" diff --git a/backend/agent/caclient.go b/backend/agent/caclient.go index 99ef1fef990d436c30a9f6b39ceae16829851495..eff984c0cbfc04df8048f005c2bc054a641e76bf 100644 --- a/backend/agent/caclient.go +++ b/backend/agent/caclient.go @@ -2,6 +2,7 @@ package agent import ( "bytes" + "context" "crypto/tls" "net/http" @@ -33,7 +34,14 @@ func NewHTTPClient() *HTTPClient { } func (c *HTTPClient) Call(url string, payload *bytes.Buffer) (*http.Response, error) { - rsp, err := c.client.Post(url, "application/json", payload) + req, err := http.NewRequestWithContext(context.Background(), http.MethodPost, url, payload) + if err != nil { + err = errors.Wrapf(err, "problem with creating POST request to %s", url) + + return nil, err + } + req.Header.Add("Content-Type", "application/json") + rsp, err := c.client.Do(req) if err != nil { err = errors.Wrapf(err, "problem with sending POST to %s", url) } diff --git a/backend/agent/kea.go b/backend/agent/kea.go index 9daeb75f5fbbd65364adfec3346d19f1af13e6f1..223547c178a0e4d62bae695f0ec58b7ce77f5957 100644 --- a/backend/agent/kea.go +++ b/backend/agent/kea.go @@ -10,7 +10,6 @@ import ( "github.com/pkg/errors" log "github.com/sirupsen/logrus" - keaconfig "isc.org/stork/appcfg/kea" keactrl "isc.org/stork/appctrl/kea" storkutil "isc.org/stork/util" diff --git a/backend/agent/kea_test.go b/backend/agent/kea_test.go index 0259d6882bdbf27dd010b0bfd6289225e5d3fd1e..46a1ccecef62671530e39a8128400416c51c1751 100644 --- a/backend/agent/kea_test.go +++ b/backend/agent/kea_test.go @@ -6,7 +6,6 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/h2non/gock.v1" - keactrl "isc.org/stork/appctrl/kea" ) diff --git a/backend/agent/keaintercept.go b/backend/agent/keaintercept.go index 9bd7cbb0fb1b4a6ffe3f6c48ce003f81fd16d640..c89a1fc4ee421586ab8b88bbadac65012bf702bf 100644 --- a/backend/agent/keaintercept.go +++ b/backend/agent/keaintercept.go @@ -4,7 +4,6 @@ import ( "sync" log "github.com/sirupsen/logrus" - agentapi "isc.org/stork/api" keactrl "isc.org/stork/appctrl/kea" ) diff --git a/backend/agent/keaintercept_test.go b/backend/agent/keaintercept_test.go index 97da8ce3eb5baaebe4b705b3101d5558da5fbb48..9dec4140b27fa959dc7bc5dad095864fc0121da4 100644 --- a/backend/agent/keaintercept_test.go +++ b/backend/agent/keaintercept_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - agentapi "isc.org/stork/api" keactrl "isc.org/stork/appctrl/kea" ) diff --git a/backend/agent/monitor.go b/backend/agent/monitor.go index 6097d2611516cf9bcd4d62a986d28dbae606d1e8..f62d20402cee71290a1c61c58a1051cb0dd94c5c 100644 --- a/backend/agent/monitor.go +++ b/backend/agent/monitor.go @@ -10,7 +10,6 @@ import ( "github.com/pkg/errors" "github.com/shirou/gopsutil/process" log "github.com/sirupsen/logrus" - storkutil "isc.org/stork/util" ) @@ -23,9 +22,11 @@ type AccessPoint struct { Key string } -// Currently supported types are: "control" and "statistics" -const AccessPointControl = "control" -const AccessPointStatistics = "statistics" +// Currently supported types are: "control" and "statistics". +const ( + AccessPointControl = "control" + AccessPointStatistics = "statistics" +) type App struct { Pid int32 @@ -33,9 +34,11 @@ type App struct { AccessPoints []AccessPoint } -// Currently supported types are: "kea" and "bind9" -const AppTypeKea = "kea" -const AppTypeBind9 = "bind9" +// Currently supported types are: "kea" and "bind9". +const ( + AppTypeKea = "kea" + AppTypeBind9 = "bind9" +) type AppMonitor interface { GetApps() []*App diff --git a/backend/agent/monitor_test.go b/backend/agent/monitor_test.go index 4ca75607feae6b6e500e88df1fd5b73dc1d8cfda..c65c332c72ec9a5060a20ee62dd84b742c1a82f3 100644 --- a/backend/agent/monitor_test.go +++ b/backend/agent/monitor_test.go @@ -29,18 +29,16 @@ func TestGetCtrlAddressFromKeaConfigNonExisting(t *testing.T) { func TestGetCtrlFromKeaConfigBadContent(t *testing.T) { // prepare kea conf file tmpFile, err := ioutil.TempFile(os.TempDir(), "prefix-") - if err != nil { - log.Fatal("Cannot create temporary file", err) - } + require.NoError(t, err) + defer os.Remove(tmpFile.Name()) text := []byte("random content") - if _, err = tmpFile.Write(text); err != nil { - log.Fatal("Failed to write to temporary file", err) - } - if err := tmpFile.Close(); err != nil { - log.Fatal(err) - } + _, err = tmpFile.Write(text) + require.NoError(t, err) + + err = tmpFile.Close() + require.NoError(t, err) // check reading from prepared file with bad content // so 0 should be returned as port @@ -52,18 +50,16 @@ func TestGetCtrlFromKeaConfigBadContent(t *testing.T) { func TestGetCtrlAddressFromKeaConfigOk(t *testing.T) { // prepare kea conf file tmpFile, err := ioutil.TempFile(os.TempDir(), "prefix-") - if err != nil { - log.Fatal("Cannot create temporary file", err) - } + require.NoError(t, err) + defer os.Remove(tmpFile.Name()) text := []byte(string("\"http-host\": \"host.example.org\", \"http-port\": 1234")) - if _, err = tmpFile.Write(text); err != nil { - log.Fatal("Failed to write to temporary file", err) - } - if err := tmpFile.Close(); err != nil { - log.Fatal(err) - } + _, err = tmpFile.Write(text) + require.NoError(t, err) + + err = tmpFile.Close() + require.NoError(t, err) // check reading from proper file address, port := getCtrlAddressFromKeaConfig(tmpFile.Name()) @@ -74,18 +70,16 @@ func TestGetCtrlAddressFromKeaConfigOk(t *testing.T) { func TestGetCtrlAddressFromKeaConfigAddress0000(t *testing.T) { // prepare kea conf file tmpFile, err := ioutil.TempFile(os.TempDir(), "prefix-") - if err != nil { - log.Fatal("Cannot create temporary file", err) - } + require.NoError(t, err) + defer os.Remove(tmpFile.Name()) text := []byte(string("\"http-host\": \"0.0.0.0\", \"http-port\": 1234")) - if _, err = tmpFile.Write(text); err != nil { - log.Fatal("Failed to write to temporary file", err) - } - if err := tmpFile.Close(); err != nil { - log.Fatal(err) - } + _, err = tmpFile.Write(text) + require.NoError(t, err) + + err = tmpFile.Close() + require.NoError(t, err) // check reading from proper file; // if CA is listening on 0.0.0.0 then 127.0.0.1 should be returned @@ -98,18 +92,16 @@ func TestGetCtrlAddressFromKeaConfigAddress0000(t *testing.T) { func TestGetCtrlAddressFromKeaConfigAddressColons(t *testing.T) { // prepare kea conf file tmpFile, err := ioutil.TempFile(os.TempDir(), "prefix-") - if err != nil { - log.Fatal("Cannot create temporary file", err) - } + require.NoError(t, err) + defer os.Remove(tmpFile.Name()) text := []byte(string("\"http-host\": \"::\", \"http-port\": 1234")) - if _, err = tmpFile.Write(text); err != nil { - log.Fatal("Failed to write to temporary file", err) - } - if err := tmpFile.Close(); err != nil { - log.Fatal(err) - } + _, err = tmpFile.Write(text) + require.NoError(t, err) + + err = tmpFile.Close() + require.NoError(t, err) // check reading from proper file; // if CA is listening on :: then ::1 should be returned diff --git a/backend/agent/prombind9exporter.go b/backend/agent/prombind9exporter.go index 3a19e4666be48bfa91ff3943f989741d9e78028f..1cfe73c7f00289e2541b5a56996ec8e1a0e3d98d 100644 --- a/backend/agent/prombind9exporter.go +++ b/backend/agent/prombind9exporter.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io/ioutil" "math" @@ -13,17 +14,16 @@ import ( "strings" "time" - "github.com/pkg/errors" + pkgerrors "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/prometheus/common/version" log "github.com/sirupsen/logrus" - "isc.org/stork" storkutil "isc.org/stork/util" ) -// Settings for Prometheus BIND 9 Exporter +// Settings for Prometheus BIND 9 Exporter. type PromBind9ExporterSettings struct { Host string `long:"prometheus-bind9-exporter-host" description:"the IP or hostname to listen on for incoming Prometheus connection" default:"0.0.0.0" env:"STORK_AGENT_PROMETHEUS_BIND9_EXPORTER_ADDRESS"` Port int `long:"prometheus-bind9-exporter-port" description:"the port to listen on for incoming Prometheus connection" default:"9119" env:"STORK_AGENT_PROMETHEUS_BIND9_EXPORTER_PORT"` @@ -453,7 +453,7 @@ func (pbe *PromBind9Exporter) qryRTTHistogram(stats map[string]float64) (uint64, rtt := strings.TrimPrefix(statName, qryRTT) bucket, err = strconv.ParseFloat(rtt, 64) if err != nil { - return 0, math.NaN(), buckets, fmt.Errorf("could not parse RTT: %s", rtt) + return 0, math.NaN(), buckets, pkgerrors.Errorf("could not parse RTT: %s", rtt) } } buckets[bucket/1000] = uint64(statValue) @@ -506,7 +506,7 @@ func (pbe *PromBind9Exporter) trafficSizesHistogram(stats map[string]float64) (c } bucket, err = strconv.ParseFloat(sizes[1], 64) if err != nil { - return 0, math.NaN(), buckets, fmt.Errorf("could not parse size: %s", sizes[1]) + return 0, math.NaN(), buckets, pkgerrors.Errorf("could not parse size: %s", sizes[1]) } } buckets[bucket] = uint64(statValue) @@ -827,7 +827,7 @@ func (pbe *PromBind9Exporter) Start() { // start HTTP server for metrics go func() { err := pbe.HTTPServer.ListenAndServe() - if err != nil && err != http.ErrServerClosed { + if err != nil && errors.Is(err, http.ErrServerClosed) { log.Errorf("problem with serving Prometheus BIND 9 Exporter: %s", err.Error()) } }() @@ -875,7 +875,7 @@ func (pbe *PromBind9Exporter) scrapeServerStat(statMap map[string]interface{}, s if statIfc != nil { stats, ok := statIfc.(map[string]interface{}) if !ok { - return nil, errors.Errorf("problem with casting '%s' interface", statName) + return nil, pkgerrors.Errorf("problem with casting '%s' interface", statName) } for labelName, labelValueIfc := range stats { // get value @@ -899,21 +899,21 @@ func (pbe *PromBind9Exporter) scrapeTimeStats(statMap map[string]interface{}) (e timeStr = getStat(statMap, "boot-time").(string) timeVal, err = time.Parse(time.RFC3339, timeStr) if err != nil { - return errors.Errorf("problem with parsing time %+s: %+v", timeStr, err) + return pkgerrors.Errorf("problem with parsing time %+s: %+v", timeStr, err) } pbe.stats.BootTime = timeVal // config_time_seconds timeStr = getStat(statMap, "config-time").(string) timeVal, err = time.Parse(time.RFC3339, timeStr) if err != nil { - return errors.Errorf("problem with parsing time %+s: %+v", timeStr, err) + return pkgerrors.Errorf("problem with parsing time %+s: %+v", timeStr, err) } pbe.stats.ConfigTime = timeVal // current_time_seconds timeStr = getStat(statMap, "current-time").(string) timeVal, err = time.Parse(time.RFC3339, timeStr) if err != nil { - return errors.Errorf("problem with parsing time %+s: %+v", timeStr, err) + return pkgerrors.Errorf("problem with parsing time %+s: %+v", timeStr, err) } pbe.stats.CurrentTime = timeVal @@ -1072,7 +1072,7 @@ func (pbe *PromBind9Exporter) scrapeViewStats(viewName string, viewStatsIfc inte func (pbe *PromBind9Exporter) setDaemonStats(rspIfc interface{}) (ret error) { rsp, ok := rspIfc.(map[string]interface{}) if !ok { - return errors.Errorf("problem with casting rspIfc: %+v", rspIfc) + return pkgerrors.Errorf("problem with casting rspIfc: %+v", rspIfc) } // boot_time_seconds @@ -1086,12 +1086,12 @@ func (pbe *PromBind9Exporter) setDaemonStats(rspIfc interface{}) (ret error) { // incoming_queries_total pbe.stats.IncomingQueries, err = pbe.scrapeServerStat(rsp, "qtypes") if err != nil { - return errors.Errorf("problem with parsing 'qtypes': %+v", err) + return pkgerrors.Errorf("problem with parsing 'qtypes': %+v", err) } // incoming_requests_total pbe.stats.IncomingRequests, err = pbe.scrapeServerStat(rsp, "opcodes") if err != nil { - return errors.Errorf("problem with parsing 'opcodes': %+v", err) + return pkgerrors.Errorf("problem with parsing 'opcodes': %+v", err) } // query_duplicates_total @@ -1103,31 +1103,31 @@ func (pbe *PromBind9Exporter) setDaemonStats(rspIfc interface{}) (ret error) { // zone_transfer_success_total pbe.stats.NsStats, err = pbe.scrapeServerStat(rsp, "nsstats") if err != nil { - return errors.Errorf("problem with parsing 'nsstats': %+v", err) + return pkgerrors.Errorf("problem with parsing 'nsstats': %+v", err) } // tasks_running // worker_threads pbe.stats.TaskMgr, err = pbe.scrapeServerStat(rsp, "taskmgr") if err != nil { - return errors.Errorf("problem with parsing 'nsstats': %+v", err) + return pkgerrors.Errorf("problem with parsing 'nsstats': %+v", err) } // Parse traffic stats. trafficIfc, ok := rsp["traffic"] if !ok { - return errors.Errorf("no 'traffic' in response: %+v", rsp) + return pkgerrors.Errorf("no 'traffic' in response: %+v", rsp) } traffic, ok := trafficIfc.(map[string]interface{}) if !ok { - return errors.Errorf("problem with casting trafficIfc: %+v", trafficIfc) + return pkgerrors.Errorf("problem with casting trafficIfc: %+v", trafficIfc) } trafficMap := make(map[string]PromBind9TrafficStats) for trafficName, trafficStatsIfc := range traffic { sizeCounts := make(map[string]float64) trafficStats, ok := trafficStatsIfc.(map[string]interface{}) if !ok { - return errors.Errorf("problem with casting '%s' interface", trafficName) + return pkgerrors.Errorf("problem with casting '%s' interface", trafficName) } for labelName, labelValueIfc := range trafficStats { // get value @@ -1147,12 +1147,12 @@ func (pbe *PromBind9Exporter) setDaemonStats(rspIfc interface{}) (ret error) { // Parse views. viewsIfc, ok := rsp["views"] if !ok { - return errors.Errorf("no 'views' in response: %+v", rsp) + return pkgerrors.Errorf("no 'views' in response: %+v", rsp) } views := viewsIfc.(map[string]interface{}) if !ok { - return errors.Errorf("problem with casting viewsIfc: %+v", viewsIfc) + return pkgerrors.Errorf("problem with casting viewsIfc: %+v", viewsIfc) } for viewName, viewStatsIfc := range views { diff --git a/backend/agent/promkeaexporter.go b/backend/agent/promkeaexporter.go index d68e42274158023f9d3a01760d444c00e25aece0..4a35dfc75b010d64a2ac95a1da22ec0139296f14 100644 --- a/backend/agent/promkeaexporter.go +++ b/backend/agent/promkeaexporter.go @@ -4,6 +4,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -12,16 +13,15 @@ import ( "sync" "time" - "github.com/pkg/errors" + pkgerrors "github.com/pkg/errors" "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promauto" "github.com/prometheus/client_golang/prometheus/promhttp" log "github.com/sirupsen/logrus" - storkutil "isc.org/stork/util" ) -// Settings for Prometheus Kea Exporter +// Settings for Prometheus Kea Exporter. type PromKeaExporterSettings struct { Host string `long:"prometheus-kea-exporter-host" description:"the IP or hostname to listen on for incoming Prometheus connection" default:"0.0.0.0" env:"STORK_AGENT_PROMETHEUS_KEA_EXPORTER_ADDRESS"` Port int `long:"prometheus-kea-exporter-port" description:"the port to listen on for incoming Prometheus connection" default:"9547" env:"STORK_AGENT_PROMETHEUS_KEA_EXPORTER_PORT"` @@ -274,7 +274,7 @@ func (pke *PromKeaExporter) Start() { // start http server for metrics go func() { err := pke.HTTPServer.ListenAndServe() - if err != nil && err != http.ErrServerClosed { + if err != nil && errors.Is(err, http.ErrServerClosed) { log.Errorf("problem with serving Prometheus Kea Exporter: %s", err.Error()) } }() @@ -349,17 +349,17 @@ func (pke *PromKeaExporter) statsCollectorLoop() { func (pke *PromKeaExporter) setDaemonStats(daemonIdx int, rspIfc interface{}, ignoredStats map[string]bool) error { rsp, ok := rspIfc.(map[string]interface{}) if !ok { - return errors.Errorf("problem with casting rspIfc: %+v", rspIfc) + return pkgerrors.Errorf("problem with casting rspIfc: %+v", rspIfc) } resultIfc, ok := rsp["result"] if !ok { - return errors.Errorf("no 'result' in response: %+v", rsp) + return pkgerrors.Errorf("no 'result' in response: %+v", rsp) } result, ok := resultIfc.(float64) if !ok { - return errors.Errorf("problem with casting resultIfc: %+v", resultIfc) + return pkgerrors.Errorf("problem with casting resultIfc: %+v", resultIfc) } if result != 0 { textIfc, ok := rsp["text"] @@ -370,20 +370,20 @@ func (pke *PromKeaExporter) setDaemonStats(daemonIdx int, rspIfc interface{}, ig log.Warnf("problem with connecting to dhcp daemon: %s", text) return nil } - return errors.Errorf("response result from Kea != 0: %d, text: %s", int(result), text) + return pkgerrors.Errorf("response result from Kea != 0: %d, text: %s", int(result), text) } } - return errors.Errorf("response result from Kea != 0: %d", int(result)) + return pkgerrors.Errorf("response result from Kea != 0: %d", int(result)) } argsIfc, ok := rsp["arguments"] if !ok { - return errors.Errorf("no 'arguments' in response: %+v", rsp) + return pkgerrors.Errorf("no 'arguments' in response: %+v", rsp) } args := argsIfc.(map[string]interface{}) if !ok { - return errors.Errorf("problem with casting argsIfc: %+v", argsIfc) + return pkgerrors.Errorf("problem with casting argsIfc: %+v", argsIfc) } for statName, statValueList1Ifc := range args { @@ -512,7 +512,7 @@ func (pke *PromKeaExporter) collectStats() error { } rspList, ok := rspsIfc.([]interface{}) if !ok { - lastErr = errors.Errorf("problem with casting rspsIfc: %+v", rspsIfc) + lastErr = pkgerrors.Errorf("problem with casting rspsIfc: %+v", rspsIfc) log.Errorf("%+v", lastErr) continue } diff --git a/backend/appcfg/kea/indexedsubnets.go b/backend/appcfg/kea/indexedsubnets.go index 11268a8a6f6390b5d875eedb0f79372ff8dbc925..92fa70afdaf16f2cfd56fd80fa2a4d3b5209a66d 100644 --- a/backend/appcfg/kea/indexedsubnets.go +++ b/backend/appcfg/kea/indexedsubnets.go @@ -21,6 +21,7 @@ func NewIndexedSubnets(rawConfig *Map) *IndexedSubnets { if rawConfig == nil { panic("provided DHCP configuration must not be nil when indexing subnets") } + return &IndexedSubnets{ Config: rawConfig, } @@ -86,5 +87,6 @@ func (is *IndexedSubnets) Populate() error { // Everything went fine, so replace indexes with fresh ones. is.ByPrefix = byPrefix + return nil } diff --git a/backend/appcfg/kea/kea_config.go b/backend/appcfg/kea/kea_config.go index a1b94aa4d2a99eceaf3226e3bbeeaae0fbc77e81..d469c776226a82095c495796192a69254ff03cce 100644 --- a/backend/appcfg/kea/kea_config.go +++ b/backend/appcfg/kea/kea_config.go @@ -42,7 +42,7 @@ type Peer struct { AutoFailover *bool `mapstructure:"auto-failover"` } -// Structure representing a configuration of the HA hooks library +// Structure representing a configuration of the HA hooks library. type HA struct { ThisServerName *string `mapstructure:"this-server-name"` Mode *string diff --git a/backend/cmd/stork-agent/main.go b/backend/cmd/stork-agent/main.go index c4bece45ebc29b1794899009f6aeebf0cf9e53a7..bb88948e70f765afceb6d4792b6adfda77911871 100644 --- a/backend/cmd/stork-agent/main.go +++ b/backend/cmd/stork-agent/main.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "os" "os/signal" @@ -8,7 +9,6 @@ import ( flags "github.com/jessevdk/go-flags" log "github.com/sirupsen/logrus" - "isc.org/stork" "isc.org/stork/agent" storkutil "isc.org/stork/util" @@ -57,8 +57,9 @@ func main() { } if _, err := parser.Parse(); err != nil { - if fe, ok := err.(*flags.Error); ok { - if fe.Type == flags.ErrHelp { + var flagsError *flags.Error + if errors.As(err, &flagsError) { + if flagsError.Type == flags.ErrHelp { os.Exit(0) } } diff --git a/backend/cmd/stork-db-migrate/main.go b/backend/cmd/stork-db-migrate/main.go index 31e15c34a984123a4a61aeb7a96fe2d40a544cad..358a164957891ccfa21573bbd3f5b802d2bd6b9a 100644 --- a/backend/cmd/stork-db-migrate/main.go +++ b/backend/cmd/stork-db-migrate/main.go @@ -1,6 +1,7 @@ package main import ( + "errors" "fmt" "os" @@ -42,7 +43,8 @@ func main() { parser := flags.NewParser(&opts, flags.Default) if _, err := parser.Parse(); err != nil { // Printing help is not an error. - if flagsErr, ok := err.(*flags.Error); ok && flagsErr.Type == flags.ErrHelp { + var flagsError *flags.Error + if errors.As(err, &flagsError) && flagsError.Type == flags.ErrHelp { os.Exit(0) } else { // We should print out what exactly went wrong. @@ -72,10 +74,10 @@ func main() { } // Use the provided credentials to connect to the database. - db, err := dbops.NewPgDbConn(&dbops.PgOptions{ + db, err := dbops.NewPgDBConn(&dbops.PgOptions{ User: opts.User, Password: opts.Password, - Database: opts.DbName, + Database: opts.DBName, Addr: fmt.Sprintf("%s:%d", opts.Host, opts.Port), }, opts.DatabaseSettings.TraceSQL != "") if err != nil { @@ -86,13 +88,15 @@ func main() { if db == nil { log.Fatal("unable to create database instance") } - defer db.Close() oldVersion, newVersion, err := dbops.Migrate(db, args...) if err != nil { - log.Fatal(err.Error()) + db.Close() + log.Fatalf(err.Error()) } + defer db.Close() + if newVersion != oldVersion { log.Infof("Migrated database from version %d to %d\n", oldVersion, newVersion) } else { diff --git a/backend/cmd/stork-server/main.go b/backend/cmd/stork-server/main.go index b83df27dde46a8c4abc78da8d71b965affd1204b..0b479cd5a4778d40bcfdc599abcad26dd7b30fd6 100644 --- a/backend/cmd/stork-server/main.go +++ b/backend/cmd/stork-server/main.go @@ -6,7 +6,6 @@ import ( "syscall" log "github.com/sirupsen/logrus" - "isc.org/stork" "isc.org/stork/server" storkutil "isc.org/stork/util" diff --git a/backend/server/agentcomm/agentcomm.go b/backend/server/agentcomm/agentcomm.go index d185ebc02594bcedef29fe362ea3d8215b61faef..aeb8931593e95d609a541c80a68ea7add5c922c7 100644 --- a/backend/server/agentcomm/agentcomm.go +++ b/backend/server/agentcomm/agentcomm.go @@ -8,14 +8,13 @@ import ( "github.com/pkg/errors" log "github.com/sirupsen/logrus" "google.golang.org/grpc" - agentapi "isc.org/stork/api" keactrl "isc.org/stork/appctrl/kea" dbmodel "isc.org/stork/server/database/model" "isc.org/stork/server/eventcenter" ) -// Settings specific to communication with Agents +// Settings specific to communication with Agents. type AgentsSettings struct { } diff --git a/backend/server/agentcomm/agentcomm_test.go b/backend/server/agentcomm/agentcomm_test.go index 941d22a1ef5cc3067094bc9a35b52cb583fffa5c..10cdcbb57165e1ebc133462bd20420e4e3610aba 100644 --- a/backend/server/agentcomm/agentcomm_test.go +++ b/backend/server/agentcomm/agentcomm_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - storktest "isc.org/stork/server/test" ) diff --git a/backend/server/agentcomm/grpcli.go b/backend/server/agentcomm/grpcli.go index 70a09262f5ac0fae0e2545ea1d01446faf74fe39..9c77ed471b1ca4feca10947c662b484bb4ccce61 100644 --- a/backend/server/agentcomm/grpcli.go +++ b/backend/server/agentcomm/grpcli.go @@ -14,7 +14,6 @@ import ( "github.com/pkg/errors" log "github.com/sirupsen/logrus" - agentapi "isc.org/stork/api" keactrl "isc.org/stork/appctrl/kea" dbmodel "isc.org/stork/server/database/model" @@ -30,18 +29,22 @@ type AccessPoint struct { Key string } -// Currently supported types are: "control" and "statistics" -const AccessPointControl = "control" -const AccessPointStatistics = "statistics" +// Currently supported types are: "control" and "statistics". +const ( + AccessPointControl = "control" + AccessPointStatistics = "statistics" +) type App struct { Type string AccessPoints []AccessPoint } -// Currently supported types are: "kea" and "bind9" -const AppTypeKea = "kea" -const AppTypeBind9 = "bind9" +// Currently supported types are: "kea" and "bind9". +const ( + AppTypeKea = "kea" + AppTypeBind9 = "bind9" +) // State of the machine. It describes multiple properties of the machine like number of CPUs // or operating system name and version. @@ -175,7 +178,7 @@ func (agents *connectedAgentsData) ForwardRndcCommand(ctx context.Context, dbApp // This is not the first time we can't communicate with the // agent. Let's be brief and say that the communication is // still broken. - err = fmt.Errorf("failed to send rndc command via the agent %s, the agent is still not responding", + err = errors.Errorf("failed to send rndc command via the agent %s, the agent is still not responding", agent.Address) } // Log the commands that failed. @@ -237,7 +240,7 @@ func (agents *connectedAgentsData) ForwardRndcCommand(ctx context.Context, dbApp // This is not the first tie the BIND9 RNDC is not responding, so let's // print the brief message. if bind9CommStats.CurrentErrorsRNDC > 1 { - result.Error = fmt.Errorf("failed to send rndc command via the agent %s, BIND9 is still not responding", + result.Error = errors.Errorf("failed to send rndc command via the agent %s, BIND9 is still not responding", agent.Address) err = result.Error // Log the commands that failed. @@ -284,7 +287,7 @@ func (agents *connectedAgentsData) ForwardToNamedStats(ctx context.Context, agen // This is not the first time we can't communicate with the // agent. Let's be brief and say that the communication is // still broken. - err = fmt.Errorf("failed to send named statistics command via the agent %s, the agent is still not responding", + err = errors.Errorf("failed to send named statistics command via the agent %s, the agent is still not responding", agent.Address) } // Log the commands that failed. @@ -330,7 +333,7 @@ func (agents *connectedAgentsData) ForwardToNamedStats(ctx context.Context, agen // This is not the first tie the BIND9 stats is not responding, so let's // print the brief message. if bind9CommStats.CurrentErrorsStats > 1 { - err = fmt.Errorf("failed to send named stats command via the agent %s, BIND9 is still not responding", + err = errors.Errorf("failed to send named stats command via the agent %s, BIND9 is still not responding", agent.Address) // Log the commands that failed. log.WithFields(log.Fields{ @@ -414,7 +417,7 @@ func (agents *connectedAgentsData) ForwardToKeaOverHTTP(ctx context.Context, dbA // This is not the first time we can't communicate with the // agent. Let's be brief and say that the communication is // still broken. - err = fmt.Errorf("failed to send Kea commands via the agent %s, the agent is still not responding", + err = errors.Errorf("failed to send Kea commands via the agent %s, the agent is still not responding", agent.Address) } agent.Stats.CurrentErrors++ @@ -607,7 +610,7 @@ func (agents *connectedAgentsData) updateErrorStatsAndRaiseEvents(agent *Agent, } } } - //log.Printf("errors CA: prev: %d, curr: %d", prevErrorsCA, keaCommStats.CurrentErrorsCA) + // log.Printf("errors CA: prev: %d, curr: %d", prevErrorsCA, keaCommStats.CurrentErrorsCA) // Set the counters for individual daemons. for dmnName, errCnt := range daemonErrorsCount { @@ -620,7 +623,7 @@ func (agents *connectedAgentsData) updateErrorStatsAndRaiseEvents(agent *Agent, // if communication with given daemon started or stopped failing then generate an event currentErrors := keaCommStats.CurrentErrorsDaemons[dmnName] - //log.Printf("errors %s: prev: %d, curr: %d", dmnName, prevErrors, currentErrors) + // log.Printf("errors %s: prev: %d, curr: %d", dmnName, prevErrors, currentErrors) if (prevErrors == 0 && currentErrors > 0) || (prevErrors > 0 && currentErrors == 0) { for _, dmn := range dbApp.Daemons { if dmn.Name == dmnName { diff --git a/backend/server/agentcomm/grpcli_test.go b/backend/server/agentcomm/grpcli_test.go index 9ac5e3a1e6f1773245f810d2d4a964a406929bfd..383ae5d574f5e074f561fd89ac81f7a952ad28f2 100644 --- a/backend/server/agentcomm/grpcli_test.go +++ b/backend/server/agentcomm/grpcli_test.go @@ -8,7 +8,6 @@ import ( "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" - agentapi "isc.org/stork/api" keactrl "isc.org/stork/appctrl/kea" dbmodel "isc.org/stork/server/database/model" @@ -204,7 +203,8 @@ func TestForwardToKeaOverHTTPWith2Cmds(t *testing.T) { "success": true } } - ]`)}, { + ]`), + }, { Status: &agentapi.Status{ Code: 0, }, @@ -213,7 +213,8 @@ func TestForwardToKeaOverHTTPWith2Cmds(t *testing.T) { "result": 1, "text": "operation failed" } - ]`)}}, + ]`), + }}, } mockAgentClient.EXPECT().ForwardToKeaOverHTTP(gomock.Any(), gomock.Any()). @@ -300,7 +301,8 @@ func TestForwardToKeaOverHTTPInvalidResponse(t *testing.T) { { "result": "a string" } - ]`)}}, + ]`), + }}, } mockAgentClient.EXPECT().ForwardToKeaOverHTTP(gomock.Any(), gomock.Any()). Return(&rsp, nil) @@ -406,7 +408,8 @@ func TestForwardToNamedStatsInvalidResponse(t *testing.T) { }, Response: `{ "views": "not the views you are looking for", - }`}, + }`, + }, } mockAgentClient.EXPECT().ForwardToNamedStats(gomock.Any(), gomock.Any()). Return(&rsp, nil) diff --git a/backend/server/agentcomm/manager.go b/backend/server/agentcomm/manager.go index 64ecef7a89bc19d8689a622fff3db81462495832..ffcb121e1247676142d246d06edf2e3941963030 100644 --- a/backend/server/agentcomm/manager.go +++ b/backend/server/agentcomm/manager.go @@ -5,7 +5,6 @@ import ( "github.com/pkg/errors" log "github.com/sirupsen/logrus" - agentapi "isc.org/stork/api" ) @@ -84,7 +83,6 @@ func (agents *connectedAgentsData) handleRequest(req *commLoopReq) { // do call ctx := context.Background() response, err := doCall(ctx, agent, req.ReqData) - if err != nil { // GetConnectedAgent remembers the grpc connection so it might // return an already existing connection. This connection may diff --git a/backend/server/agentcomm/puller.go b/backend/server/agentcomm/puller.go index 8c7302800978e1453993909bb8f6d008ff670117..ac55f1c01bef6f257eb30b1960177ec1891418da 100644 --- a/backend/server/agentcomm/puller.go +++ b/backend/server/agentcomm/puller.go @@ -5,7 +5,6 @@ import ( "time" log "github.com/sirupsen/logrus" - dbops "isc.org/stork/server/database" dbmodel "isc.org/stork/server/database/model" ) @@ -18,7 +17,7 @@ type PeriodicPuller struct { pullerName string intervalSettingName string pullFunc func() (int, error) - Db *dbops.PgDB + DB *dbops.PgDB Agents ConnectedAgents Ticker *time.Ticker Interval int64 @@ -56,7 +55,7 @@ func NewPeriodicPuller(db *dbops.PgDB, agents ConnectedAgents, pullerName, inter pullerName: pullerName, intervalSettingName: intervalSettingName, pullFunc: pullFunc, - Db: db, + DB: db, Agents: agents, Ticker: time.NewTicker(time.Duration(interval) * time.Second), Interval: interval, @@ -103,7 +102,7 @@ func (puller *PeriodicPuller) pullerLoop() { } // Check if the interval has changed in the database. If so, recreate the ticker. - interval, err := dbmodel.GetSettingInt(puller.Db, puller.intervalSettingName) + interval, err := dbmodel.GetSettingInt(puller.DB, puller.intervalSettingName) if err != nil { log.Errorf("problem with getting interval setting %s from db: %+v", puller.intervalSettingName, err) diff --git a/backend/server/agentcomm/puller_test.go b/backend/server/agentcomm/puller_test.go index fb0555c6985770661913071514ad10c5b38400ef..8cbb3abf481e7ef08c107e298048f524ae8f86bd 100644 --- a/backend/server/agentcomm/puller_test.go +++ b/backend/server/agentcomm/puller_test.go @@ -5,7 +5,6 @@ import ( "time" "github.com/stretchr/testify/require" - dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/apps/bind9/appbind9.go b/backend/server/apps/bind9/appbind9.go index 86286e3269bd570c25d3ba630967eab4048cab40..e5bb0bd2ca8c68128088e2eaf76e508a3a575cd9 100644 --- a/backend/server/apps/bind9/appbind9.go +++ b/backend/server/apps/bind9/appbind9.go @@ -7,7 +7,6 @@ import ( "time" log "github.com/sirupsen/logrus" - "isc.org/stork/server/agentcomm" dbops "isc.org/stork/server/database" dbmodel "isc.org/stork/server/database/model" diff --git a/backend/server/apps/bind9/appbind9_test.go b/backend/server/apps/bind9/appbind9_test.go index f486574182eef3c2246f7af191f9454b5d5943f7..dcf46840fe365ffb2ad78b318b2d5ea4d57d2a36 100644 --- a/backend/server/apps/bind9/appbind9_test.go +++ b/backend/server/apps/bind9/appbind9_test.go @@ -6,7 +6,6 @@ import ( "time" "github.com/stretchr/testify/require" - agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" diff --git a/backend/server/apps/bind9/statspuller.go b/backend/server/apps/bind9/statspuller.go index 635f990e970e79bdc6f7c5a68e1a5a73345d90e4..fe7365e614341dd6434d47dc7deced36e78ab8f5 100644 --- a/backend/server/apps/bind9/statspuller.go +++ b/backend/server/apps/bind9/statspuller.go @@ -5,7 +5,6 @@ import ( "github.com/go-pg/pg/v9" log "github.com/sirupsen/logrus" - "isc.org/stork/server/agentcomm" dbmodel "isc.org/stork/server/database/model" "isc.org/stork/server/eventcenter" @@ -42,7 +41,7 @@ func (statsPuller *StatsPuller) Shutdown() { // pulled and last encountered error. func (statsPuller *StatsPuller) pullStats() (int, error) { // get list of all bind9 apps from database - dbApps, err := dbmodel.GetAppsByType(statsPuller.Db, dbmodel.AppTypeBind9) + dbApps, err := dbmodel.GetAppsByType(statsPuller.DB, dbmodel.AppTypeBind9) if err != nil { return 0, err } @@ -112,5 +111,5 @@ func (statsPuller *StatsPuller) getStatsFromApp(dbApp *dbmodel.App) error { } dbApp.Daemons[0].Bind9Daemon.Stats.NamedStats = namedStats - return dbmodel.UpdateDaemon(statsPuller.Db, dbApp.Daemons[0]) + return dbmodel.UpdateDaemon(statsPuller.DB, dbApp.Daemons[0]) } diff --git a/backend/server/apps/bind9/statspuller_test.go b/backend/server/apps/bind9/statspuller_test.go index e6bd8d16ba289d8022b04ddd7a620f31281ef817..37454b9ddfad2d2947f9c7a702e180b562dce125 100644 --- a/backend/server/apps/bind9/statspuller_test.go +++ b/backend/server/apps/bind9/statspuller_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - "isc.org/stork/server/agentcomm" agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" diff --git a/backend/server/apps/kea/appkea.go b/backend/server/apps/kea/appkea.go index 24b75625f6eeff606dded7fa5edee534c85328d9..fc219fe1d3deb80f0c1c810a607ccf2b7f6aec6c 100644 --- a/backend/server/apps/kea/appkea.go +++ b/backend/server/apps/kea/appkea.go @@ -7,7 +7,6 @@ import ( errors "github.com/pkg/errors" log "github.com/sirupsen/logrus" - keaconfig "isc.org/stork/appcfg/kea" keactrl "isc.org/stork/appctrl/kea" "isc.org/stork/server/agentcomm" @@ -81,7 +80,7 @@ func findDaemonEnsureKeaDaemonIsNotNilAndSetActiveFlag(dbApp *dbmodel.App, daemo // The state, that is stored into dbApp, includes: version and config of CA. // It also returns: // - list of all Kea daemons -// - list of DHCP daemons (dhcpv4 and/or dhcpv6) +// - list of DHCP daemons (dhcpv4 and/or dhcpv6). func getStateFromCA(ctx context.Context, agents agentcomm.ConnectedAgents, dbApp *dbmodel.App, daemonsMap map[string]*dbmodel.Daemon, daemonsErrors map[string]string) (keactrl.Daemons, keactrl.Daemons, error) { // prepare the command to get config and version from CA cmds := []*keactrl.Command{ @@ -117,7 +116,7 @@ func getStateFromCA(ctx context.Context, agents agentcomm.ConnectedAgents, dbApp case err != nil: errStr += fmt.Sprintf("%s", err) case len(versionGetResp) == 0: - errStr += fmt.Sprintf("empty response") + errStr += "empty response" default: errStr += fmt.Sprintf("result == %d, msg: %s", versionGetResp[0].Result, versionGetResp[0].Text) } @@ -333,93 +332,96 @@ func findChangesAndRaiseEvents(dbApp *dbmodel.App, daemonsMap map[string]*dbmode var newDaemons []*dbmodel.Daemon var events []*dbmodel.Event - // If app already existed then... - if dbApp.ID != 0 { - newCADmn, ok := daemonsMap["ca"] - if !ok || !newCADmn.Active { - for _, oldDmn := range dbApp.Daemons { - if oldDmn.Active { - // add ref to app in daemon so it is available in CreateEvent - oldDmn.App = dbApp - oldDmn.Active = false - errStr, ok := daemonsErrors[oldDmn.Name] - if !ok { - errStr = "" - } - ev := eventcenter.CreateEvent(dbmodel.EvError, "{daemon} is unreachable", errStr, dbApp.Machine, dbApp, oldDmn) - events = append(events, ev) - } - } - if dbApp.Active { - ev := eventcenter.CreateEvent(dbmodel.EvError, "{app} is unreachable", dbApp.Machine, dbApp) - events = append(events, ev) - } - return false, false, nil, events - } - + // If this is new app + if dbApp.ID == 0 { for name := range daemonsMap { dmn := daemonsMap[name] // if all daemons are active then whole app is active newActive = newActive && dmn.Active + // if this is new daemon and it is not active then disable its monitoring + if !dmn.Active { + dmn.Monitored = false + } + // if this is a new app then just add detected daemon newDaemons = append(newDaemons, dmn) + } - // Determine changes in app daemons state and store them as events. - // Later this events will be passed to EventCenter when all the changes - // are stored in database. - for _, oldDmn := range dbApp.Daemons { - if dmn.Name == oldDmn.Name { - // add ref to app in daemon so it is available in CreateEvent - oldDmn.App = dbApp - // check if daemon changed Active state - if dmn.Active != oldDmn.Active { - lvl := dbmodel.EvWarning - text := "{daemon} is " - if dmn.Active && !oldDmn.Active { - text += "reachable now" - } else if !dmn.Active && oldDmn.Active { - text += "unreachable" - lvl = dbmodel.EvError - } - errStr, ok := daemonsErrors[oldDmn.Name] - if !ok { - errStr = "" - } - ev := eventcenter.CreateEvent(lvl, text, errStr, dbApp.Machine, dbApp, oldDmn) - events = append(events, ev) - - // check if daemon has been restarted - } else if dmn.Uptime < oldDmn.Uptime { - text := "{daemon} has been restarted" - ev := eventcenter.CreateEvent(dbmodel.EvWarning, text, dbApp.Machine, dbApp, oldDmn) - events = append(events, ev) - } + return newActive, true, newDaemons, events + } - // check if daemon changed Version - if dmn.Version != oldDmn.Version { - text := fmt.Sprintf("{daemon} version changed from %s to %s", - oldDmn.Version, dmn.Version) - ev := eventcenter.CreateEvent(dbmodel.EvWarning, text, dbApp.Machine, dbApp, oldDmn) - events = append(events, ev) - } - break + // If app already existed then... + newCADmn, ok := daemonsMap["ca"] + if !ok || !newCADmn.Active { + for _, oldDmn := range dbApp.Daemons { + if oldDmn.Active { + // add ref to app in daemon so it is available in CreateEvent + oldDmn.App = dbApp + oldDmn.Active = false + errStr, ok := daemonsErrors[oldDmn.Name] + if !ok { + errStr = "" } + ev := eventcenter.CreateEvent(dbmodel.EvError, "{daemon} is unreachable", errStr, dbApp.Machine, dbApp, oldDmn) + events = append(events, ev) } } - } else { - for name := range daemonsMap { - dmn := daemonsMap[name] - // if all daemons are active then whole app is active - newActive = newActive && dmn.Active + if dbApp.Active { + ev := eventcenter.CreateEvent(dbmodel.EvError, "{app} is unreachable", dbApp.Machine, dbApp) + events = append(events, ev) + } + return false, false, nil, events + } + + for name := range daemonsMap { + dmn := daemonsMap[name] + // if all daemons are active then whole app is active + newActive = newActive && dmn.Active + + // if this is a new app then just add detected daemon + newDaemons = append(newDaemons, dmn) + + // Determine changes in app daemons state and store them as events. + // Later this events will be passed to EventCenter when all the changes + // are stored in database. + for _, oldDmn := range dbApp.Daemons { + if dmn.Name == oldDmn.Name { + // add ref to app in daemon so it is available in CreateEvent + oldDmn.App = dbApp + // check if daemon changed Active state + if dmn.Active != oldDmn.Active { + lvl := dbmodel.EvWarning + text := "{daemon} is " + if dmn.Active && !oldDmn.Active { + text += "reachable now" + } else if !dmn.Active && oldDmn.Active { + text += "unreachable" + lvl = dbmodel.EvError + } + errStr, ok := daemonsErrors[oldDmn.Name] + if !ok { + errStr = "" + } + ev := eventcenter.CreateEvent(lvl, text, errStr, dbApp.Machine, dbApp, oldDmn) + events = append(events, ev) - // if this is new daemon and it is not active then disable its monitoring - if !dmn.Active { - dmn.Monitored = false - } + // check if daemon has been restarted + } else if dmn.Uptime < oldDmn.Uptime { + text := "{daemon} has been restarted" + ev := eventcenter.CreateEvent(dbmodel.EvWarning, text, dbApp.Machine, dbApp, oldDmn) + events = append(events, ev) + } - // if this is a new app then just add detected daemon - newDaemons = append(newDaemons, dmn) + // check if daemon changed Version + if dmn.Version != oldDmn.Version { + text := fmt.Sprintf("{daemon} version changed from %s to %s", + oldDmn.Version, dmn.Version) + ev := eventcenter.CreateEvent(dbmodel.EvWarning, text, dbApp.Machine, dbApp, oldDmn) + events = append(events, ev) + } + break + } } } diff --git a/backend/server/apps/kea/appkea_test.go b/backend/server/apps/kea/appkea_test.go index 39209f7f4ba06b5b5e54602d9c4fddfbf71b4fea..18a18151da08a9210c6ab5bdcdc816a7f963660c 100644 --- a/backend/server/apps/kea/appkea_test.go +++ b/backend/server/apps/kea/appkea_test.go @@ -5,8 +5,6 @@ import ( "testing" "github.com/stretchr/testify/require" - //log "github.com/sirupsen/logrus" - keactrl "isc.org/stork/appctrl/kea" agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" @@ -360,7 +358,7 @@ func TestGetDaemonHooksFrom1Daemon(t *testing.T) { require.Equal(t, "hook_abc.so", hooks[0]) } -// Check getting hooks of 2 daemons +// Check getting hooks of 2 daemons. func TestGetDaemonHooksFrom2Daemons(t *testing.T) { dbApp := dbmodel.App{ Daemons: []*dbmodel.Daemon{ diff --git a/backend/server/apps/kea/host.go b/backend/server/apps/kea/host.go index 28d038bf685ba2a203ae021287708cf5c1f9783f..608c7e49368c6f2006e30ee53a607ee94fd162ab 100644 --- a/backend/server/apps/kea/host.go +++ b/backend/server/apps/kea/host.go @@ -6,7 +6,6 @@ import ( errors "github.com/pkg/errors" log "github.com/sirupsen/logrus" - keactrl "isc.org/stork/appctrl/kea" "isc.org/stork/server/agentcomm" dbops "isc.org/stork/server/database" @@ -66,13 +65,13 @@ func (puller *HostsPuller) Shutdown() { // Triggers fetch of the host reservations from the monitored Kea apps. func (puller *HostsPuller) pullData() (int, error) { // Get the list of all Kea apps from the database. - apps, err := dbmodel.GetAppsByType(puller.Db, dbmodel.AppTypeKea) + apps, err := dbmodel.GetAppsByType(puller.DB, dbmodel.AppTypeKea) if err != nil { return 0, err } // Get sequence number to be associated with updated and inserted hosts. - seq, err := dbmodel.GetNextBulkUpdateSeq(puller.Db) + seq, err := dbmodel.GetNextBulkUpdateSeq(puller.DB) if err != nil { err = errors.WithMessagef(err, "problem with getting next bulk update sequence number fetching hosts from Kea apps") return 0, err @@ -82,7 +81,7 @@ func (puller *HostsPuller) pullData() (int, error) { var lastErr error appsOkCnt := 0 for i := range apps { - err := updateHostsFromHostCmds(puller.Db, puller.Agents, &apps[i], seq) + err := updateHostsFromHostCmds(puller.DB, puller.Agents, &apps[i], seq) if err != nil { lastErr = err log.Errorf("error occurred while fetching hosts from app %d: %+v", apps[i].ID, err) @@ -93,7 +92,7 @@ func (puller *HostsPuller) pullData() (int, error) { // Remove all associations between the hosts and tha apps that are no longer // present. - err = dbmodel.DeleteLocalHostsWithOtherSeq(puller.Db, seq, "api") + err = dbmodel.DeleteLocalHostsWithOtherSeq(puller.DB, seq, "api") if err != nil { log.Errorf("error occurred while deleting old hosts after update from Kea apps: %+v", err) } diff --git a/backend/server/apps/kea/host_test.go b/backend/server/apps/kea/host_test.go index f2a1ae95809d5a5dc0ccfb390f1840b01adfcf63..852b9039162b500da6c05273d38efa27e9e1d0a8 100644 --- a/backend/server/apps/kea/host_test.go +++ b/backend/server/apps/kea/host_test.go @@ -8,7 +8,6 @@ import ( "testing" require "github.com/stretchr/testify/require" - keactrl "isc.org/stork/appctrl/kea" agentcommtest "isc.org/stork/server/agentcomm/test" dbops "isc.org/stork/server/database" diff --git a/backend/server/apps/kea/rps.go b/backend/server/apps/kea/rps.go index 63cb9f3b2f75fa84644b0c91091e590bed7d5870..f014a373929f38cb65012e9129b1a1e58f46d854 100644 --- a/backend/server/apps/kea/rps.go +++ b/backend/server/apps/kea/rps.go @@ -1,13 +1,11 @@ package kea import ( - "fmt" "time" "github.com/go-pg/pg/v9" "github.com/pkg/errors" log "github.com/sirupsen/logrus" - keactrl "isc.org/stork/appctrl/kea" dbmodel "isc.org/stork/server/database/model" storkutil "isc.org/stork/util" @@ -21,7 +19,7 @@ type RpsWorker struct { Interval2 time.Duration } -// Represents a time/value pair +// Represents a time/value pair. type StatSample struct { SampledAt time.Time // time value was recorded Value int64 // statistic value @@ -29,7 +27,7 @@ type StatSample struct { // Represents a response from the single Kea server to the statistic-get // for pkt4-ack-sent: -//{ +// { // "command": "statistic-get", // "arguments": { // "pkt4-ack-sent": [ @@ -38,21 +36,21 @@ type StatSample struct { // ] // }, // "result": 0 -//} +// }. type StatGetResponse4 struct { keactrl.ResponseHeader Arguments *ResponseArguments4 `json:"arguments,omitempty"` } // The list of value/timestamp pairs returned as pkt4-ack-sent -// as the value for command response "Arguments" element +// as the value for command response "Arguments" element. type ResponseArguments4 struct { Samples []interface{} `json:"pkt4-ack-sent"` } // Represents a response from the single Kea server to the statistic-get // for pkt6-reply-sent: -//{ +// { // "command": "statistic-get", // "arguments": { // "pkt6-reply-sent": [ @@ -61,14 +59,14 @@ type ResponseArguments4 struct { // ] // }, // "result": 0 -//} +// }. type StatGetResponse6 struct { keactrl.ResponseHeader Arguments *ResponseArguments6 `json:"arguments,omitempty"` } // The list of value/timestamp pairs returned as pkt6-reply-sent -// as the value for command response "Arguments" element +// as the value for command response "Arguments" element. type ResponseArguments6 struct { Samples []interface{} `json:"pkt6-reply-sent"` } @@ -103,7 +101,8 @@ func RpsAddCmd4(cmds *[]*keactrl.Command, dhcp4Daemons *keactrl.Daemons) interfa *cmds = append(*cmds, &keactrl.Command{ Command: "statistic-get", Daemons: dhcp4Daemons, - Arguments: &dhcp4Arguments}) + Arguments: &dhcp4Arguments, + }) return (&[]StatGetResponse4{}) } @@ -114,7 +113,8 @@ func RpsAddCmd6(cmds *[]*keactrl.Command, dhcp6Daemons *keactrl.Daemons) interfa *cmds = append(*cmds, &keactrl.Command{ Command: "statistic-get", Daemons: dhcp6Daemons, - Arguments: &dhcp6Arguments}) + Arguments: &dhcp6Arguments, + }) return (&[]StatGetResponse6{}) } @@ -122,7 +122,7 @@ func RpsAddCmd6(cmds *[]*keactrl.Command, dhcp6Daemons *keactrl.Daemons) interfa func (rpsWorker *RpsWorker) Response4Handler(daemon *dbmodel.Daemon, response interface{}) error { statsResp4, ok := response.(*[]StatGetResponse4) if !ok { - return fmt.Errorf("response type is invalid: %+v", response) + return errors.Errorf("response type is invalid: %+v", response) } samples, err := rpsWorker.extractSamples4(*statsResp4) @@ -147,7 +147,7 @@ func (rpsWorker *RpsWorker) Response4Handler(daemon *dbmodel.Daemon, response in func (rpsWorker *RpsWorker) Response6Handler(daemon *dbmodel.Daemon, response interface{}) error { statsResp6, ok := response.(*[]StatGetResponse6) if !ok { - return fmt.Errorf("response type is invalid: %+v", response) + return errors.Errorf("response type is invalid: %+v", response) } samples, err := rpsWorker.extractSamples6(*statsResp6) @@ -171,22 +171,22 @@ func (rpsWorker *RpsWorker) Response6Handler(daemon *dbmodel.Daemon, response in // Exract the list of statistic samples from a dhcp4 statistic-get response if the response is valid. func (rpsWorker *RpsWorker) extractSamples4(statsResp []StatGetResponse4) ([]interface{}, error) { if len(statsResp) == 0 { - err := fmt.Errorf("empty RPS response") + err := errors.Errorf("empty RPS response") return nil, err } if statsResp[0].Result != 0 { - err := fmt.Errorf("error result in RPS response: %+v", statsResp) + err := errors.Errorf("error result in RPS response: %+v", statsResp) return nil, err } if statsResp[0].Arguments == nil { - err := fmt.Errorf("missing Arguments from RPS response %+v", statsResp) + err := errors.Errorf("missing Arguments from RPS response %+v", statsResp) return nil, err } if statsResp[0].Arguments.Samples == nil { - err := fmt.Errorf("missing Samples from RPS response: %+v", statsResp) + err := errors.Errorf("missing Samples from RPS response: %+v", statsResp) return nil, err } @@ -196,22 +196,22 @@ func (rpsWorker *RpsWorker) extractSamples4(statsResp []StatGetResponse4) ([]int // Exract the list of statistic samples from a dhcp6 statistic-get response if the response is valid. func (rpsWorker *RpsWorker) extractSamples6(statsResp []StatGetResponse6) ([]interface{}, error) { if len(statsResp) == 0 { - err := fmt.Errorf("empty RPS response") + err := errors.Errorf("empty RPS response") return nil, err } if statsResp[0].Result != 0 { - err := fmt.Errorf("error result in RPS response: %+v", statsResp) + err := errors.Errorf("error result in RPS response: %+v", statsResp) return nil, err } if statsResp[0].Arguments == nil { - err := fmt.Errorf("missing Arguments from RPS response: %+v", statsResp) + err := errors.Errorf("missing Arguments from RPS response: %+v", statsResp) return nil, err } if statsResp[0].Arguments.Samples == nil { - err := fmt.Errorf("missing Samples from RPS response: %+v", statsResp) + err := errors.Errorf("missing Samples from RPS response: %+v", statsResp) return nil, err } @@ -296,7 +296,7 @@ func (rpsWorker *RpsWorker) updateKeaDaemonRpsStats(daemon *dbmodel.Daemon) erro return dbmodel.UpdateDaemon(rpsWorker.db, daemon) } -// Calculate the RPS for the first row in a set of RpsIntervals +// Calculate the RPS for the first row in a set of RpsIntervals. func calculateRps(totals []*dbmodel.RpsInterval) int { if len(totals) == 0 { return 0 @@ -330,16 +330,16 @@ func getFirstSample(samples []interface{}) (int64, time.Time, error) { if len(samples) == 0 { // Not enough rows - return 0, sampledAt, fmt.Errorf("sampleList is empty") + return 0, sampledAt, errors.Errorf("sampleList is empty") } row, ok := samples[0].([]interface{}) if !ok { - return 0, sampledAt, fmt.Errorf("problem with casting sample row: %+v", samples[0]) + return 0, sampledAt, errors.Errorf("problem with casting sample row: %+v", samples[0]) } if len(row) != 2 { - return 0, sampledAt, fmt.Errorf("row has incorrect number of values: %+v", row) + return 0, sampledAt, errors.Errorf("row has incorrect number of values: %+v", row) } // Not sure why unmarshalling makes it a float64, but we need an int64. @@ -348,12 +348,12 @@ func getFirstSample(samples []interface{}) (int64, time.Time, error) { return value, sampledAt, nil } -// "Static" constant for dhcp4 statistic-get command argument +// "Static" constant for dhcp4 statistic-get command argument. func RpsGetDhcp4Arguments() map[string]interface{} { return map[string]interface{}{"name": "pkt4-ack-sent"} } -// "Static" constant for dhcp6 statistic-get command argument +// "Static" constant for dhcp6 statistic-get command argument. func RpsGetDhcp6Arguments() map[string]interface{} { return map[string]interface{}{"name": "pkt6-reply-sent"} } diff --git a/backend/server/apps/kea/rps_test.go b/backend/server/apps/kea/rps_test.go index 19701d714b704b2abd0f49bd3c98572f5296e8a2..859dfe2a1618dc2bfb70551fa3024e801539ef0a 100644 --- a/backend/server/apps/kea/rps_test.go +++ b/backend/server/apps/kea/rps_test.go @@ -6,7 +6,6 @@ import ( "time" "github.com/stretchr/testify/require" - keactrl "isc.org/stork/appctrl/kea" dbops "isc.org/stork/server/database" dbmodel "isc.org/stork/server/database/model" @@ -48,7 +47,7 @@ func TestRpsWorkerPullRps(t *testing.T) { db, _, teardown := dbtest.SetupDatabaseTestCase(t) defer teardown() - var makeJSON4 = func(callNo int) string { + makeJSON4 := func(callNo int) string { return (fmt.Sprintf(`[{ "result": 0, "text": "Everything is fine", @@ -57,7 +56,7 @@ func TestRpsWorkerPullRps(t *testing.T) { }}]`, (callNo * 5))) } - var makeJSON6 = func(callNo int) string { + makeJSON6 := func(callNo int) string { return (fmt.Sprintf(`[{ "result": 0, "text": "Everything is fine", @@ -175,7 +174,7 @@ func TestRpsWorkerValuePermutations(t *testing.T) { // Array of expected RpsInterval.Responses for each interval row added expectedResponses := []int64{100, 35, 0, 15, 0, 10, 0, 17} - var makeJSON4 = func(value int64) string { + makeJSON4 := func(value int64) string { resp := fmt.Sprintf(`[{ "result": 0, "text": "Everything is fine", @@ -269,7 +268,7 @@ func rpsTestAddMachine(t *testing.T, db *dbops.PgDB, dhcp4Active bool, dhcp6Acti return a.Daemons[0], a.Daemons[1] } -// Verifies RPS values for both intervals for a given daemon +// Verifies RPS values for both intervals for a given daemon. func checkDaemonRpsStats(t *testing.T, db *dbops.PgDB, keaDaemonID int64, interval1 int, interval2 int) { daemon := &dbmodel.KeaDHCPDaemon{} err := db.Model(daemon). @@ -302,7 +301,7 @@ func getExpectedRps(rpsIntervals []*dbmodel.RpsInterval, endIdx int) int { return (int(responses / duration)) } -// Marshall a given json response to a DHCP4 command and pass that into Response4Handler +// Marshall a given json response to a DHCP4 command and pass that into Response4Handler. func rpsTestInvokeResponse4Handler(rps *RpsWorker, daemon *dbmodel.Daemon, jsonResponse string) error { cmds := []*keactrl.Command{} responses := []interface{}{} @@ -315,7 +314,7 @@ func rpsTestInvokeResponse4Handler(rps *RpsWorker, daemon *dbmodel.Daemon, jsonR return err } -// Marshall a given json response to a DHCP6 command and pass that into Response6Handler +// Marshall a given json response to a DHCP6 command and pass that into Response6Handler. func rpsTestInvokeResponse6Handler(rps *RpsWorker, daemon *dbmodel.Daemon, jsonResponse string) error { cmds := []*keactrl.Command{} responses := []interface{}{} diff --git a/backend/server/apps/kea/service.go b/backend/server/apps/kea/service.go index 1ab41dc4ec87cd35b63eeaad88354ae53311166c..c90c3c8ebd2ed9a7f34540b94fdd0bf7674f6c73 100644 --- a/backend/server/apps/kea/service.go +++ b/backend/server/apps/kea/service.go @@ -1,10 +1,9 @@ package kea import ( + keaconfig "isc.org/stork/appcfg/kea" dbops "isc.org/stork/server/database" dbmodel "isc.org/stork/server/database/model" - - keaconfig "isc.org/stork/appcfg/kea" ) // Checks if the specified Kea daemon belongs to a given HA service. diff --git a/backend/server/apps/kea/statspuller.go b/backend/server/apps/kea/statspuller.go index 7f33a98a496a2bac77ba9363b3183be13b79f9d4..a90bd2fb4727762d16fe084af64b6ec06928c441 100644 --- a/backend/server/apps/kea/statspuller.go +++ b/backend/server/apps/kea/statspuller.go @@ -2,12 +2,10 @@ package kea import ( "context" - "fmt" "github.com/go-pg/pg/v9" "github.com/pkg/errors" log "github.com/sirupsen/logrus" - keactrl "isc.org/stork/appctrl/kea" "isc.org/stork/server/agentcomm" dbmodel "isc.org/stork/server/database/model" @@ -126,7 +124,7 @@ func getStatsFromLocalSubnets(localSubnets []*dbmodel.LocalSubnet, family int, a // of apps for which the stats were successfully pulled and last encountered error. func (statsPuller *StatsPuller) pullStats() (int, error) { // get list of all kea apps from database - dbApps, err := dbmodel.GetAppsByType(statsPuller.Db, dbmodel.AppTypeKea) + dbApps, err := dbmodel.GetAppsByType(statsPuller.DB, dbmodel.AppTypeKea) if err != nil { return 0, err } @@ -147,7 +145,7 @@ func (statsPuller *StatsPuller) pullStats() (int, error) { log.Printf("completed pulling lease stats from Kea apps: %d/%d succeeded", appsOkCnt, len(dbApps)) // estimate addresses utilization for subnets - subnets, err := dbmodel.GetSubnetsWithLocalSubnets(statsPuller.Db) + subnets, err := dbmodel.GetSubnetsWithLocalSubnets(statsPuller.DB) if err != nil { return appsOkCnt, err } @@ -189,7 +187,7 @@ func (statsPuller *StatsPuller) pullStats() (int, error) { if netTotalPds > 0 { usedPds = int16(1000 * netAssignedPds / netTotalPds) } - err := dbmodel.UpdateUtilizationInSharedNetwork(statsPuller.Db, sharedNetworkID, used, usedPds) + err := dbmodel.UpdateUtilizationInSharedNetwork(statsPuller.DB, sharedNetworkID, used, usedPds) if err != nil { lastErr = err log.Errorf("cannot update utilization (%d, %d) in shared network %d: %s", used, usedPds, sharedNetworkID, err) @@ -237,7 +235,7 @@ func (statsPuller *StatsPuller) pullStats() (int, error) { snMaxUsedPds = 0 } // udpate utilization in subnet in db - err = sn.UpdateUtilization(statsPuller.Db, snMaxUsed, snMaxUsedPds) + err = sn.UpdateUtilization(statsPuller.DB, snMaxUsed, snMaxUsedPds) if err != nil { lastErr = err log.Errorf("cannot update utilization (%d, %d) in subnet %d: %s", snMaxUsed, snMaxUsedPds, sn.ID, err) @@ -246,7 +244,7 @@ func (statsPuller *StatsPuller) pullStats() (int, error) { } // update global statistics in db - err = dbmodel.SetStats(statsPuller.Db, statsMap) + err = dbmodel.SetStats(statsPuller.DB, statsMap) if err != nil { lastErr = err } @@ -285,21 +283,21 @@ func (statsPuller *StatsPuller) storeDaemonStats(response interface{}, subnetsMa statsResp, ok := response.(*[]StatLeaseGetResponse) if !ok { - return fmt.Errorf("response is empty: %+v", sr) + return errors.Errorf("response is empty: %+v", sr) } sr = *statsResp if len(sr) == 0 { - return fmt.Errorf("response is empty: %+v", sr) + return errors.Errorf("response is empty: %+v", sr) } if sr[0].Arguments == nil { - return fmt.Errorf("missing Arguments from Lease Stats response %+v", sr[0]) + return errors.Errorf("missing Arguments from Lease Stats response %+v", sr[0]) } resultSet := &sr[0].Arguments.ResultSet if resultSet == nil { - return fmt.Errorf("missing ResultSet from Lease Stats response %+v", sr[0]) + return errors.Errorf("missing ResultSet from Lease Stats response %+v", sr[0]) } for _, row := range resultSet.Rows { @@ -330,7 +328,7 @@ func (statsPuller *StatsPuller) storeDaemonStats(response interface{}, subnetsMa log.Error(lastErr.Error()) continue } - err := sn.UpdateStats(statsPuller.Db, stats) + err := sn.UpdateStats(statsPuller.DB, stats) if err != nil { log.Errorf("problem with updating Kea stats for local subnet id %d, app id %d: %s", sn.LocalSubnetID, dbApp.ID, err.Error()) lastErr = err @@ -415,7 +413,6 @@ func (statsPuller *StatsPuller) getStatsFromApp(dbApp *dbmodel.App) error { ctx := context.Background() cmdsResult, err := statsPuller.Agents.ForwardToKeaOverHTTP(ctx, dbApp, cmds, responses...) - if err != nil { return err } @@ -432,7 +429,7 @@ func (statsPuller *StatsPuller) getStatsFromApp(dbApp *dbmodel.App) error { // Was part of getStatsFromApp() until lint_go complained about cognitive complexity. func (statsPuller *StatsPuller) processAppResponses(dbApp *dbmodel.App, cmds []*keactrl.Command, cmdDaemons []*dbmodel.Daemon, responses []interface{}) error { // Lease statistic processing needs app's local subnets - subnets, err := dbmodel.GetAppLocalSubnets(statsPuller.Db, dbApp.ID) + subnets, err := dbmodel.GetAppLocalSubnets(statsPuller.DB, dbApp.ID) if err != nil { return err } diff --git a/backend/server/apps/kea/statspuller_test.go b/backend/server/apps/kea/statspuller_test.go index 234886756535c09af3f4c961884dfe2c6f4f911f..639d8c1392d78088004a29a4d716296c0a0f1117 100644 --- a/backend/server/apps/kea/statspuller_test.go +++ b/backend/server/apps/kea/statspuller_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/stretchr/testify/require" - keactrl "isc.org/stork/appctrl/kea" agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" @@ -38,7 +37,7 @@ func TestStatsPullerBasic(t *testing.T) { // Check if Kea response to stat-leaseX-get command is handled correctly when it is // empty or when stats hooks library is not loaded. The RPS responses are valid, -// they have their own unit tests in rps_test.go +// they have their own unit tests in rps_test.go. func TestStatsPullerEmptyResponse(t *testing.T) { db, _, teardown := dbtest.SetupDatabaseTestCase(t) defer teardown() diff --git a/backend/server/apps/kea/status.go b/backend/server/apps/kea/status.go index 49c9e249bcf3f82eb5f4403ce57caefa32b6a57c..7a20d6f887f5b6c241c3bcb48487fdbf9534e5cb 100644 --- a/backend/server/apps/kea/status.go +++ b/backend/server/apps/kea/status.go @@ -6,7 +6,6 @@ import ( "time" log "github.com/sirupsen/logrus" - keactrl "isc.org/stork/appctrl/kea" "isc.org/stork/server/agentcomm" dbops "isc.org/stork/server/database" @@ -225,12 +224,25 @@ func updateHAServiceStatus(status *HAServersStatus, daemon *dbmodel.Daemon, serv } } +// Iterates over the slice of HA services and updates them in the database. +func (puller *HAStatusPuller) commitHAServicesStatus(appID int64, services []dbmodel.Service) { + for i := range services { + // Update the information about the HA service in the database. + err := dbmodel.UpdateBaseHAService(puller.DB, services[i].HAService) + if err != nil { + log.Errorf("error occurred while updating HA services status for Kea app %d: %+v", appID, err) + + continue + } + } +} + // Gets the status of the Kea apps and stores useful information in the database. // The High Availability status is stored in the database for those apps which // have the HA enabled. func (puller *HAStatusPuller) pullData() (int, error) { // Get the list of all Kea apps from the database. - apps, err := dbmodel.GetAppsByType(puller.Db, dbmodel.AppTypeKea) + apps, err := dbmodel.GetAppsByType(puller.DB, dbmodel.AppTypeKea) if err != nil { return 0, err } @@ -239,100 +251,107 @@ func (puller *HAStatusPuller) pullData() (int, error) { appsOkCnt := 0 appsCnt := 0 for i := range apps { - // Before contacting the DHCP server, let's check if there is any service - // the app belongs to. - dbServices, err := dbmodel.GetDetailedServicesByAppID(puller.Db, apps[i].ID) - if err != nil { - log.Errorf("error while getting services for Kea app %d: %+v", apps[i].ID, err) - continue + pulled, ok := puller.pullDataForApp(&apps[i]) + if pulled { + appsCnt++ } - // No services for this app, so nothing to do. - if len(dbServices) == 0 { - continue + if ok { + appsOkCnt++ } + } + log.Printf("completed pulling DHCP status from Kea apps: %d/%d succeeded", appsOkCnt, appsCnt) - // Pick only those services for the app that have the HA type. At the - // same time reset the values in case the server doesn't respond to the - // command. These values will indicate that we can't say what is happening - // with the server we failed to connect to. - var haServices []dbmodel.Service - for j := range dbServices { - if dbServices[j].HAService == nil { - continue - } - for _, d := range apps[i].Daemons { - switch d.ID { - case dbServices[j].HAService.PrimaryID: - dbServices[j].HAService.PrimaryLastState = HAStatusUnavailable - dbServices[j].HAService.PrimaryLastScopes = []string{} - dbServices[j].HAService.PrimaryReachable = false - case dbServices[j].HAService.SecondaryID: - dbServices[j].HAService.SecondaryLastState = HAStatusUnavailable - dbServices[j].HAService.SecondaryLastScopes = []string{} - dbServices[j].HAService.SecondaryReachable = false - } - haServices = append(haServices, dbServices[j]) + return appsOkCnt, lastErr +} + +// Gets the status of a Kea app and stores useful information in the database. +// The High Availability status is stored in the database for those apps which +// have the HA enabled. +func (puller *HAStatusPuller) pullDataForApp(app *dbmodel.App) (bool, bool) { + // Before contacting the DHCP server, let's check if there is any service + // the app belongs to. + dbServices, err := dbmodel.GetDetailedServicesByAppID(puller.DB, app.ID) + if err != nil { + log.Errorf("error while getting services for Kea app %d: %+v", app.ID, err) + return false, false + } + // No services for this app, so nothing to do. + if len(dbServices) == 0 { + return false, false + } + + // Pick only those services for the app that have the HA type. At the + // same time reset the values in case the server doesn't respond to the + // command. These values will indicate that we can't say what is happening + // with the server we failed to connect to. + var haServices []dbmodel.Service + for j := range dbServices { + if dbServices[j].HAService == nil { + continue + } + for _, d := range app.Daemons { + switch d.ID { + case dbServices[j].HAService.PrimaryID: + dbServices[j].HAService.PrimaryLastState = HAStatusUnavailable + dbServices[j].HAService.PrimaryLastScopes = []string{} + dbServices[j].HAService.PrimaryReachable = false + case dbServices[j].HAService.SecondaryID: + dbServices[j].HAService.SecondaryLastState = HAStatusUnavailable + dbServices[j].HAService.SecondaryLastScopes = []string{} + dbServices[j].HAService.SecondaryReachable = false } + haServices = append(haServices, dbServices[j]) } + } - appsCnt++ - ctx := context.Background() - // Send the status-get command to both DHCPv4 and DHCPv6 servers. - appStatus, err := getDHCPStatus(ctx, puller.Agents, &apps[i]) - if err != nil { - log.Errorf("error occurred while getting Kea app %d status: %+v", apps[i].ID, err) + ctx := context.Background() + // Send the status-get command to both DHCPv4 and DHCPv6 servers. + appStatus, err := getDHCPStatus(ctx, puller.Agents, app) + if err != nil { + log.Errorf("error occurred while getting Kea app %d status: %+v", app.ID, err) + + return true, false + } + // Go over the returned status values and match with the daemons. + for _, status := range appStatus { + // If no HA status, there is nothing to do. + if status.HAServers == nil && len(status.HA) == 0 { + continue } - // Go over the returned status values and match with the daemons. - for _, status := range appStatus { - // If no HA status, there is nothing to do. - if status.HAServers == nil && len(status.HA) == 0 { - continue - } - // Find the matching service for the returned status. - index := -1 + // Find the matching service for the returned status. + index := -1 - for i := range haServices { - if haServices[i].HAService.HAType == status.Daemon { - index = i - } - } - if index < 0 { - continue - } - service := haServices[index].HAService - for _, daemon := range apps[i].Daemons { - // Update the HA service status only if the given server is primary - // or secondary. - if service.PrimaryID == daemon.ID || service.SecondaryID == daemon.ID { - // todo: Currently Kea supports only one HA service per daemon. This - // will change but for now it is safe to assume that only one status - // is returned. Supporting more requires some mechanisms to - // distinguish the HA relationships which should be first designed - // on the Kea side. - if len(status.HA) > 0 { - updateHAServiceStatus(&status.HA[0].HAServers, daemon, service) - } else if status.HAServers != nil { - updateHAServiceStatus(status.HAServers, daemon, service) - } - } + for i := range haServices { + if haServices[i].HAService.HAType == status.Daemon { + index = i } } - - // Update the services as appropriate regardless if we successfully communicated - // with the servers or not. - for j := range haServices { - // Update the information about the HA service in the database. - err = dbmodel.UpdateBaseHAService(puller.Db, haServices[j].HAService) - if err != nil { - log.Errorf("error occurred while updating HA services status for Kea app %d: %+v", apps[i].ID, err) - continue + if index < 0 { + continue + } + service := haServices[index].HAService + for _, daemon := range app.Daemons { + // Update the HA service status only if the given server is primary + // or secondary. + if service.PrimaryID == daemon.ID || service.SecondaryID == daemon.ID { + // todo: Currently Kea supports only one HA service per daemon. This + // will change but for now it is safe to assume that only one status + // is returned. Supporting more requires some mechanisms to + // distinguish the HA relationships which should be first designed + // on the Kea side. + if len(status.HA) > 0 { + updateHAServiceStatus(&status.HA[0].HAServers, daemon, service) + } else if status.HAServers != nil { + updateHAServiceStatus(status.HAServers, daemon, service) + } } } - - appsOkCnt++ } - log.Printf("completed pulling DHCP status from Kea apps: %d/%d succeeded", appsOkCnt, appsCnt) - return appsOkCnt, lastErr + + // Update the services as appropriate regardless if we successfully communicated + // with the servers or not. + puller.commitHAServicesStatus(app.ID, haServices) + return true, true } // Sends the status-get command to Kea DHCP servers and returns this status to the caller. diff --git a/backend/server/apps/kea/status_test.go b/backend/server/apps/kea/status_test.go index 5fe4d43ce741b6c8a008dedc7bc45bcf6591e12e..5863e25fd2dc22d764d4307ef464d77b10a2263b 100644 --- a/backend/server/apps/kea/status_test.go +++ b/backend/server/apps/kea/status_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/stretchr/testify/require" - keactrl "isc.org/stork/appctrl/kea" agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" @@ -317,7 +316,7 @@ func mockGetStatusNoHA(callNo int, cmdResponses []interface{}) { } // Generates test response to status-get command indicating an error and -// lacking argument.s +// lacking arguments. func mockGetStatusError(callNo int, cmdResponses []interface{}) { daemons, _ := keactrl.NewDaemons("dhcp4") command, _ := keactrl.NewCommand("status-get", daemons, nil) diff --git a/backend/server/apps/kea/subnet.go b/backend/server/apps/kea/subnet.go index a6e22774b56b3b5bd73f142c933b5007a68c1f98..51ed3a0f227f826723061e6c9ca1e4992c5bdf73 100644 --- a/backend/server/apps/kea/subnet.go +++ b/backend/server/apps/kea/subnet.go @@ -3,7 +3,6 @@ package kea import ( "github.com/pkg/errors" log "github.com/sirupsen/logrus" - dbops "isc.org/stork/server/database" dbmodel "isc.org/stork/server/database/model" ) @@ -49,64 +48,70 @@ func findMatchingSubnet(subnet *dbmodel.Subnet, existingSubnets *dbmodel.Indexed func detectSharedNetworks(db *dbops.PgDB, config *dbmodel.KeaConfig, family int, app *dbmodel.App) (networks []dbmodel.SharedNetwork, err error) { // Get all shared networks and the subnets within those networks from the // application configuration. - if networkList, ok := config.GetTopLevelList("shared-networks"); ok { - // If there are no shared networks there is nothing to do. - if len(networkList) == 0 { - return networks, nil - } + networkList, ok := config.GetTopLevelList("shared-networks") + if !ok { + return networks, err + } + + // If there are no shared networks there is nothing to do. + if len(networkList) == 0 { + return networks, nil + } + + // We have to match the configured shared networks with the ones we + // already have in the database. + dbNetworks, err := dbmodel.GetAllSharedNetworks(db, family) + if err != nil { + return []dbmodel.SharedNetwork{}, err + } - // We have to match the configured shared networks with the ones we - // already have in the database. - dbNetworks, err := dbmodel.GetAllSharedNetworks(db, family) + // For each network in the app's configuration we will do such matching. + for _, n := range networkList { + networkMap, ok := n.(map[string]interface{}) + if !ok { + continue + } + // Parse the configured network. + network, err := dbmodel.NewSharedNetworkFromKea(&networkMap, family) + if err != nil { + log.Warnf("skipping invalid shared network: %v", err) + continue + } + dbNetwork, err := sharedNetworkExists(db, network, dbNetworks) if err != nil { return []dbmodel.SharedNetwork{}, err } - - // For each network in the app's configuration we will do such matching. - for _, n := range networkList { - if networkMap, ok := n.(map[string]interface{}); ok { - // Parse the configured network. - network, err := dbmodel.NewSharedNetworkFromKea(&networkMap, family) - if err != nil { - log.Warnf("skipping invalid shared network: %v", err) - continue - } - dbNetwork, err := sharedNetworkExists(db, network, dbNetworks) - if err != nil { - return []dbmodel.SharedNetwork{}, err - } - if dbNetwork != nil { - // Create indexes for the existing subnets to improve performance of - // matching new subnets with them. - indexedSubnets := dbmodel.NewIndexedSubnets(dbNetwork.Subnets) - if ok := indexedSubnets.Populate(); !ok { - log.Warnf("skipping shared network %s because building indexes failed due to duplicates", dbNetwork.Name) + if dbNetwork != nil { + // Create indexes for the existing subnets to improve performance of + // matching new subnets with them. + indexedSubnets := dbmodel.NewIndexedSubnets(dbNetwork.Subnets) + if ok := indexedSubnets.Populate(); !ok { + log.Warnf("skipping shared network %s because building indexes failed due to duplicates", dbNetwork.Name) + + continue + } + // Go over the configured subnets and see if they belong to that + // shared network already. + for _, s := range network.Subnets { + subnet := s + existingSubnet := findMatchingSubnet(&subnet, indexedSubnets) + if existingSubnet == nil { + dbNetwork.Subnets = append(dbNetwork.Subnets, subnet) + } else { + // Subnet already exists and may contain some hosts. Let's + // merge the hosts from the new subnet into the existing subnet. + hosts, err := mergeSubnetHosts(db, existingSubnet, &subnet, app) + if err != nil { + log.Warnf("skipping hosts for subnet %s after hosts merge failure: %v", + subnet.Prefix, err) continue } - // Go over the configured subnets and see if they belong to that - // shared network already. - for _, s := range network.Subnets { - subnet := s - existingSubnet := findMatchingSubnet(&subnet, indexedSubnets) - if existingSubnet == nil { - dbNetwork.Subnets = append(dbNetwork.Subnets, subnet) - } else { - // Subnet already exists and may contain some hosts. Let's - // merge the hosts from the new subnet into the existing subnet. - hosts, err := mergeSubnetHosts(db, existingSubnet, &subnet, app) - if err != nil { - log.Warnf("skipping hosts for subnet %s after hosts merge failure: %v", - subnet.Prefix, err) - continue - } - existingSubnet.Hosts = hosts - } - } - networks = append(networks, *dbNetwork) - } else { - networks = append(networks, *network) + existingSubnet.Hosts = hosts } } + networks = append(networks, *dbNetwork) + } else { + networks = append(networks, *network) } } return networks, nil @@ -123,51 +128,50 @@ func detectSubnets(db *dbops.PgDB, config *dbmodel.KeaConfig, family int, app *d } // Get top level subnets not associated with any shared networks. - if subnetList, ok := config.GetTopLevelList(subnetParamName); ok { - // Nothing to do if no subnets are configured. - if len(subnetList) == 0 { - return subnets, nil - } + subnetList, ok := config.GetTopLevelList(subnetParamName) + if !ok || len(subnetList) == 0 { + return subnets, err + } - // Fetch all top-level subnets from the database to perform matching. For now - // it is better to get all of them because this is just a single query rather - // than many but in the future we should probably revise that when the number - // of subnets grows. - dbSubnets, err := dbmodel.GetAllSubnets(db, family) - if err != nil { - return []dbmodel.Subnet{}, err - } - indexedSubnets := dbmodel.NewIndexedSubnets(dbSubnets) - if ok := indexedSubnets.Populate(); !ok { - err = errors.Errorf("failed to build indexes for existing subnets because duplicates are present") - return []dbmodel.Subnet{}, err - } + // Fetch all top-level subnets from the database to perform matching. For now + // it is better to get all of them because this is just a single query rather + // than many but in the future we should probably revise that when the number + // of subnets grows. + dbSubnets, err := dbmodel.GetAllSubnets(db, family) + if err != nil { + return []dbmodel.Subnet{}, err + } + indexedSubnets := dbmodel.NewIndexedSubnets(dbSubnets) + if ok := indexedSubnets.Populate(); !ok { + err = errors.Errorf("failed to build indexes for existing subnets because duplicates are present") + + return []dbmodel.Subnet{}, err + } - // Iterate over the configured subnets. - for _, s := range subnetList { - if subnetMap, ok := s.(map[string]interface{}); ok { - // Parse the configured subnet. - subnet, err := dbmodel.NewSubnetFromKea(&subnetMap) + // Iterate over the configured subnets. + for _, s := range subnetList { + if subnetMap, ok := s.(map[string]interface{}); ok { + // Parse the configured subnet. + subnet, err := dbmodel.NewSubnetFromKea(&subnetMap) + if err != nil { + log.Warnf("skipping invalid subnet: %v", err) + continue + } + existingSubnet := findMatchingSubnet(subnet, indexedSubnets) + if existingSubnet != nil { + subnets = append(subnets, *existingSubnet) + // Subnet already exists and may contain some hosts. Let's + // merge the hosts from the new subnet into the existing subnet. + hosts, err := mergeSubnetHosts(db, existingSubnet, subnet, app) if err != nil { - log.Warnf("skipping invalid subnet: %v", err) + log.Warnf("skipping hosts for subnet %s after hosts merge failure: %v", + subnet.Prefix, err) continue } - existingSubnet := findMatchingSubnet(subnet, indexedSubnets) - if existingSubnet != nil { - subnets = append(subnets, *existingSubnet) - // Subnet already exists and may contain some hosts. Let's - // merge the hosts from the new subnet into the existing subnet. - hosts, err := mergeSubnetHosts(db, existingSubnet, subnet, app) - if err != nil { - log.Warnf("skipping hosts for subnet %s after hosts merge failure: %v", - subnet.Prefix, err) - continue - } - // Assign merged hosts to the subnet. - subnets[len(subnets)-1].Hosts = hosts - } else { - subnets = append(subnets, *subnet) - } + // Assign merged hosts to the subnet. + subnets[len(subnets)-1].Hosts = hosts + } else { + subnets = append(subnets, *subnet) } } } diff --git a/backend/server/apps/statepuller.go b/backend/server/apps/statepuller.go index d6118cd85391c75a07f99a0fca9b1ec234152cd4..37542a49fa4717c8233df39d8e60fac6f104bde4 100644 --- a/backend/server/apps/statepuller.go +++ b/backend/server/apps/statepuller.go @@ -6,7 +6,6 @@ import ( "github.com/pkg/errors" log "github.com/sirupsen/logrus" - "isc.org/stork/server/agentcomm" "isc.org/stork/server/apps/bind9" "isc.org/stork/server/apps/kea" @@ -45,7 +44,7 @@ func (puller *StatePuller) Shutdown() { // Gets the status of machines and their apps and stores useful information in the database. func (puller *StatePuller) pullData() (int, error) { // get list of all machines from database - dbMachines, err := dbmodel.GetAllMachines(puller.Db) + dbMachines, err := dbmodel.GetAllMachines(puller.DB) if err != nil { return 0, err } @@ -56,7 +55,7 @@ func (puller *StatePuller) pullData() (int, error) { for _, dbM := range dbMachines { dbM2 := dbM ctx := context.Background() - errStr := GetMachineAndAppsState(ctx, puller.Db, &dbM2, puller.Agents, puller.EventCenter) + errStr := GetMachineAndAppsState(ctx, puller.DB, &dbM2, puller.Agents, puller.EventCenter) if errStr != "" { lastErr = errors.New(errStr) log.Errorf("error occurred while getting info from machine %d: %s", dbM2.ID, errStr) diff --git a/backend/server/apps/statepuller_test.go b/backend/server/apps/statepuller_test.go index 61fa468aa9a42393a5010f850b3b6cd94d582445..e31a3c0fbb267dd800cacae9eda632d86db6f269 100644 --- a/backend/server/apps/statepuller_test.go +++ b/backend/server/apps/statepuller_test.go @@ -4,9 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - - //keactrl "isc.org/stork/appctrl/kea" - //"isc.org/stork/server/apps/kea" "isc.org/stork/server/agentcomm" agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" diff --git a/backend/server/auth/auth_test.go b/backend/server/auth/auth_test.go index fc28fde0d8451c7c24fde0436a0df41a92889fe1..bbf67171d6509a7f559dd25b35a28a34dec3180a 100644 --- a/backend/server/auth/auth_test.go +++ b/backend/server/auth/auth_test.go @@ -1,6 +1,7 @@ package auth import ( + "context" "net/http" "testing" @@ -25,7 +26,7 @@ func authorizeAccept(t *testing.T, groupID int, path string) bool { } // Create request with the specified path and authorize. - req, _ := http.NewRequest("GET", "http://example.org/api"+path, nil) + req, _ := http.NewRequestWithContext(context.Background(), "GET", "http://example.org/api"+path, nil) ok, err := Authorize(user, req) require.NoError(t, err) diff --git a/backend/server/database/connection.go b/backend/server/database/connection.go index e8e8854387d8b193988ff7098e2aa604ceb7bd1d..2fe23c8ac0de404ce92b275e1fa017d2a252add2 100644 --- a/backend/server/database/connection.go +++ b/backend/server/database/connection.go @@ -2,20 +2,21 @@ package dbops import ( "context" + "errors" "fmt" "os" "time" "github.com/go-pg/pg/v9" "github.com/go-pg/pg/v9/orm" - "github.com/pkg/errors" + pkgerrors "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) -type DbLogger struct{} +type DBLogger struct{} // Hook run before SQL query execution. -func (d DbLogger) BeforeQuery(c context.Context, q *pg.QueryEvent) (context.Context, error) { +func (d DBLogger) BeforeQuery(c context.Context, q *pg.QueryEvent) (context.Context, error) { // When making queries on the system_user table we want to make sure that // we don't expose actual data in the logs, especially password. if model, ok := q.Model.(orm.TableModel); ok { @@ -28,7 +29,7 @@ func (d DbLogger) BeforeQuery(c context.Context, q *pg.QueryEvent) (context.Cont } } } - var query, err = q.FormattedQuery() + query, err := q.FormattedQuery() // FormattedQuery returns a tuple of query and error. The error in most cases is nil, and // we don't want to print it. On the other hand, all logging is printed on stdout. We want // to print here to stder, so it's possible to redirect just the queries to a file. @@ -42,36 +43,39 @@ func (d DbLogger) BeforeQuery(c context.Context, q *pg.QueryEvent) (context.Cont } // Hook run after SQL query execution. -func (d DbLogger) AfterQuery(c context.Context, q *pg.QueryEvent) error { +func (d DBLogger) AfterQuery(c context.Context, q *pg.QueryEvent) error { return nil } // Create only new PgDB instance. -func NewPgDbConn(pgParams *pg.Options, tracing bool) (*PgDB, error) { +func NewPgDBConn(pgParams *pg.Options, tracing bool) (*PgDB, error) { db := pg.Connect(pgParams) // Add tracing hooks if requested. if tracing { - db.AddQueryHook(DbLogger{}) + db.AddQueryHook(DBLogger{}) } log.Printf("checking connection to database") // Test connection to database. var err error for tries := 0; tries < 10; tries++ { - var n int + var ( + n int + pgError pg.Error + ) _, err = db.QueryOne(pg.Scan(&n), "SELECT 1") if err == nil { break - } else if pgErr, ok := err.(pg.Error); ok && pgErr.Field('S') == "FATAL" { + } + if errors.As(err, &pgError) && pgError.Field('S') == "FATAL" { break - } else { - log.Printf("problem with connecting to db, trying again in 2 seconds, %d/10: %s", tries+1, err) } + log.Printf("problem with connecting to db, trying again in 2 seconds, %d/10: %s", tries+1, err) time.Sleep(2 * time.Second) } if err != nil { - return nil, errors.Wrapf(err, "unable to connect to the database using provided credentials") + return nil, pkgerrors.Wrapf(err, "unable to connect to the database using provided credentials") } return db, nil } @@ -82,7 +86,7 @@ func NewPgDB(settings *DatabaseSettings) (*PgDB, error) { Password(settings) // Make a connection to DB (tracing is enabled at this stage if set to all (migrations and run-time)) - db, err := NewPgDbConn(settings.PgParams(), settings.TraceSQL == "all") + db, err := NewPgDBConn(settings.PgParams(), settings.TraceSQL == "all") if err != nil { return nil, err } @@ -100,7 +104,7 @@ func NewPgDB(settings *DatabaseSettings) (*PgDB, error) { // Enable tracing here, if we were told to enable only at run-time if settings.TraceSQL == "run" { - db.AddQueryHook(DbLogger{}) + db.AddQueryHook(DBLogger{}) } log.Infof("connected to database %s:%d, schema version: %d", settings.Host, settings.Port, newVer) @@ -120,7 +124,7 @@ func Transaction(dbIface interface{}) (tx *pg.Tx, rollback func(), commit func() if ok { tx, err = db.Begin() if err != nil { - err = errors.Wrapf(err, "problem with starting database transaction") + err = pkgerrors.Wrapf(err, "problem with starting database transaction") } rollback = func() { // We neither capture nor log any error here because it would @@ -133,14 +137,14 @@ func Transaction(dbIface interface{}) (tx *pg.Tx, rollback func(), commit func() commit = func() (err error) { err = tx.Commit() if err != nil { - err = errors.Wrapf(err, "problem with committing the transaction") + err = pkgerrors.Wrapf(err, "problem with committing the transaction") } return err } } else { tx, ok = dbIface.(*pg.Tx) if !ok { - err = errors.New("unsupported type of the database transaction object provided") + err = pkgerrors.New("unsupported type of the database transaction object provided") } rollback = func() {} commit = func() (err error) { diff --git a/backend/server/database/migrations.go b/backend/server/database/migrations.go index e14183a19f84886a25215c6e7c974e2c95884738..0521ca63d10c33890bed98299818867fbc89ca04 100644 --- a/backend/server/database/migrations.go +++ b/backend/server/database/migrations.go @@ -7,7 +7,9 @@ import ( "github.com/go-pg/migrations/v7" "github.com/go-pg/pg/v9" "github.com/pkg/errors" - _ "isc.org/stork/server/database/migrations" // TODO: document why it is blank imported + + // TODO: document why it is blank imported. + _ "isc.org/stork/server/database/migrations" ) // Checks if the migrations table exists, i.e. the 'init' command was called. @@ -31,7 +33,6 @@ func Toss(db *PgDB) error { // Migrate the database down to 0. _, _, err := Migrate(db, "reset") - if err != nil { return err } @@ -63,7 +64,7 @@ func Migrate(db *PgDB, args ...string) (oldVersion, newVersion int64, err error) if oldVer, _, err = migrations.Run(db, "version"); err != nil { return oldVer, oldVer, errors.Wrapf(err, "problem with checking database version") } - var toVer, err = strconv.ParseInt(args[1], 10, 64) + toVer, err := strconv.ParseInt(args[1], 10, 64) if err != nil { return oldVer, oldVer, errors.Wrapf(err, "can't parse -t argument %s as database version (expected integer)", args[1]) } diff --git a/backend/server/database/model/access_point.go b/backend/server/database/model/access_point.go index e4e038cf55d2c022eaaff44989a007f05fc46432..31a2cc8be52212e0a3dc27fc5d0bbec23077ad53 100644 --- a/backend/server/database/model/access_point.go +++ b/backend/server/database/model/access_point.go @@ -10,8 +10,10 @@ type AccessPoint struct { Key string } -const AccessPointControl = "control" -const AccessPointStatistics = "statistics" +const ( + AccessPointControl = "control" + AccessPointStatistics = "statistics" +) // AppendAccessPoint is an utility function that appends an access point to a // list. diff --git a/backend/server/database/model/app.go b/backend/server/database/model/app.go index d1e0236875e385cdbedb7295db628a546199754f..041cc94acce78e032fa426450a2010c19546d563 100644 --- a/backend/server/database/model/app.go +++ b/backend/server/database/model/app.go @@ -1,12 +1,12 @@ package dbmodel import ( + "errors" "time" "github.com/go-pg/pg/v9" "github.com/go-pg/pg/v9/orm" - "github.com/pkg/errors" - + pkgerrors "github.com/pkg/errors" dbops "isc.org/stork/server/database" ) @@ -50,7 +50,7 @@ func updateAppAccessPoints(tx *pg.Tx, app *App, update bool) (err error) { q = q.Where("type NOT IN (?)", pg.In(types)) _, err = q.Delete() if err != nil { - return errors.Wrapf(err, "problem with removing access points from app %d", app.ID) + return pkgerrors.Wrapf(err, "problem with removing access points from app %d", app.ID) } } @@ -65,7 +65,7 @@ func updateAppAccessPoints(tx *pg.Tx, app *App, update bool) (err error) { _, err = tx.Model(point).Insert() } if err != nil { - return errors.Wrapf(err, "problem with adding access point to app %d: %v", app.ID, point) + return pkgerrors.Wrapf(err, "problem with adding access point to app %d: %v", app.ID, point) } } return nil @@ -94,7 +94,7 @@ func updateAppDaemons(tx *pg.Tx, app *App) ([]*Daemon, []*Daemon, error) { var deletedDaemons []*Daemon _, err := q.Returning("*").Delete(&deletedDaemons) if err != nil { - return nil, nil, errors.Wrapf(err, "problem with deleting daemons for an updated app %d", app.ID) + return nil, nil, pkgerrors.Wrapf(err, "problem with deleting daemons for an updated app %d", app.ID) } // Add updated daemons. @@ -112,32 +112,24 @@ func updateAppDaemons(tx *pg.Tx, app *App) ([]*Daemon, []*Daemon, error) { _, err = tx.Model(daemon).WherePK().Update() } if err != nil { - return nil, nil, errors.Wrapf(err, "problem with upserting daemon to app %d: %v", app.ID, daemon) + return nil, nil, pkgerrors.Wrapf(err, "problem with upserting daemon to app %d: %v", app.ID, daemon) } if daemon.KeaDaemon != nil { // Make sure that the kea_daemon references the daemon. daemon.KeaDaemon.DaemonID = daemon.ID - if daemon.KeaDaemon.ID == 0 { - _, err = tx.Model(daemon.KeaDaemon).Insert() - } else { - _, err = tx.Model(daemon.KeaDaemon).WherePK().Update() - } + err = upsertInTransaction(tx, daemon.KeaDaemon.ID, daemon.KeaDaemon) if err != nil { - return nil, nil, errors.Wrapf(err, "problem with upserting Kea daemon to app %d: %v", + return nil, nil, pkgerrors.Wrapf(err, "problem with upserting Kea daemon to app %d: %v", app.ID, daemon.KeaDaemon) } if daemon.KeaDaemon.KeaDHCPDaemon != nil { // Make sure that the kea_dhcp_daemon references the kea_daemon. daemon.KeaDaemon.KeaDHCPDaemon.KeaDaemonID = daemon.KeaDaemon.ID - if daemon.KeaDaemon.KeaDHCPDaemon.ID == 0 { - _, err = tx.Model(daemon.KeaDaemon.KeaDHCPDaemon).Insert() - } else { - _, err = tx.Model(daemon.KeaDaemon.KeaDHCPDaemon).WherePK().Update() - } + err = upsertInTransaction(tx, daemon.KeaDaemon.KeaDHCPDaemon.ID, daemon.KeaDaemon.KeaDHCPDaemon) if err != nil { - return nil, nil, errors.Wrapf(err, "problem with upserting Kea DHCP daemon to app %d: %v", + return nil, nil, pkgerrors.Wrapf(err, "problem with upserting Kea DHCP daemon to app %d: %v", app.ID, daemon.KeaDaemon.KeaDHCPDaemon) } } @@ -150,7 +142,7 @@ func updateAppDaemons(tx *pg.Tx, app *App) ([]*Daemon, []*Daemon, error) { _, err = tx.Model(daemon.Bind9Daemon).WherePK().Update() } if err != nil { - return nil, nil, errors.Wrapf(err, "problem with upserting BIND9 daemon to app %d: %v", + return nil, nil, pkgerrors.Wrapf(err, "problem with upserting BIND9 daemon to app %d: %v", app.ID, daemon.Bind9Daemon) } } @@ -169,7 +161,7 @@ func updateAppDaemons(tx *pg.Tx, app *App) ([]*Daemon, []*Daemon, error) { } _, err := q.Delete() if err != nil { - return nil, nil, errors.Wrapf(err, "problem with deleting log targets for updated daemon %d", + return nil, nil, pkgerrors.Wrapf(err, "problem with deleting log targets for updated daemon %d", daemon.ID) } @@ -187,7 +179,7 @@ func updateAppDaemons(tx *pg.Tx, app *App) ([]*Daemon, []*Daemon, error) { _, err = tx.Model(daemon.LogTargets[i]).WherePK().Update() } if err != nil { - return nil, nil, errors.Wrapf(err, "problem with upserting log target %s to daemon %d: %v", + return nil, nil, pkgerrors.Wrapf(err, "problem with upserting log target %s to daemon %d: %v", daemon.LogTargets[i].Output, daemon.ID, daemon) } } @@ -211,21 +203,21 @@ func AddApp(dbIface interface{}, app *App) ([]*Daemon, error) { err = tx.Insert(app) if err != nil { - return nil, errors.Wrapf(err, "problem with inserting app %v", app) + return nil, pkgerrors.Wrapf(err, "problem with inserting app %v", app) } addedDaemons, deletedDaemons, err := updateAppDaemons(tx, app) if err != nil { - return nil, errors.WithMessagef(err, "problem with inserting daemons for a new app") + return nil, pkgerrors.WithMessagef(err, "problem with inserting daemons for a new app") } if len(deletedDaemons) > 0 { - return nil, errors.Errorf("problem with deleting daemons for a new app") + return nil, pkgerrors.Errorf("problem with deleting daemons for a new app") } // Add access points. err = updateAppAccessPoints(tx, app, false) if err != nil { - return nil, errors.Wrapf(err, "problem with adding access points to app: %+v", app) + return nil, pkgerrors.Wrapf(err, "problem with adding access points to app: %+v", app) } // Commit the changes if necessary. @@ -254,18 +246,18 @@ func UpdateApp(dbIface interface{}, app *App) ([]*Daemon, []*Daemon, error) { err = tx.Update(app) if err != nil { - return nil, nil, errors.Wrapf(err, "problem with updating app %v", app) + return nil, nil, pkgerrors.Wrapf(err, "problem with updating app %v", app) } addedDaemons, deletedDaemons, err := updateAppDaemons(tx, app) if err != nil { - return nil, nil, errors.WithMessagef(err, "problem with updating daemons for app %d", app.ID) + return nil, nil, pkgerrors.WithMessagef(err, "problem with updating daemons for app %d", app.ID) } // Update access points. err = updateAppAccessPoints(tx, app, true) if err != nil { - return nil, nil, errors.WithMessagef(err, "problem with updating access points to app: %+v", app) + return nil, nil, pkgerrors.WithMessagef(err, "problem with updating access points to app: %+v", app) } // Commit the changes if necessary. @@ -287,10 +279,10 @@ func GetAppByID(db *pg.DB, id int64) (*App, error) { q = q.Relation("Daemons.LogTargets") q = q.Where("app.id = ?", id) err := q.Select() - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } else if err != nil { - return nil, errors.Wrapf(err, "problem with getting app %v", id) + return nil, pkgerrors.Wrapf(err, "problem with getting app %v", id) } return &app, nil } @@ -307,7 +299,7 @@ func GetAppsByMachine(db *pg.DB, machineID int64) ([]*App, error) { q = q.OrderExpr("id ASC") err := q.Select() if err != nil { - return nil, errors.Wrapf(err, "problem with getting apps") + return nil, pkgerrors.Wrapf(err, "problem with getting apps") } return apps, nil } @@ -333,7 +325,7 @@ func GetAppsByType(db *pg.DB, appType string) ([]App, error) { q = q.OrderExpr("id ASC") err := q.Select() if err != nil { - return nil, errors.Wrapf(err, "problem with getting %s apps from database", appType) + return nil, pkgerrors.Wrapf(err, "problem with getting %s apps from database", appType) } return apps, nil } @@ -347,7 +339,7 @@ func GetAppsByType(db *pg.DB, appType string) ([]App, error) { // order is used. func GetAppsByPage(db *pg.DB, offset int64, limit int64, filterText *string, appType string, sortField string, sortDir SortDirEnum) ([]App, int64, error) { if limit == 0 { - return nil, 0, errors.New("limit should be greater than 0") + return nil, 0, pkgerrors.New("limit should be greater than 0") } var apps []App @@ -380,10 +372,10 @@ func GetAppsByPage(db *pg.DB, offset int64, limit int64, filterText *string, app total, err := q.SelectAndCount() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return []App{}, 0, nil } - return nil, 0, errors.Wrapf(err, "problem with getting apps") + return nil, 0, pkgerrors.Wrapf(err, "problem with getting apps") } return apps, int64(total), nil } @@ -403,7 +395,7 @@ func GetAllApps(db *pg.DB) ([]App, error) { // retrieve apps from db err := q.Select() if err != nil { - return nil, errors.Wrapf(err, "problem with getting apps") + return nil, pkgerrors.Wrapf(err, "problem with getting apps") } return apps, nil } @@ -411,7 +403,7 @@ func GetAllApps(db *pg.DB) ([]App, error) { func DeleteApp(db *pg.DB, app *App) error { err := db.Delete(app) if err != nil { - return errors.Wrapf(err, "problem with deleting app %v", app.ID) + return pkgerrors.Wrapf(err, "problem with deleting app %v", app.ID) } return nil } @@ -455,6 +447,7 @@ func (app *App) GetLocalSubnetID(prefix string) int64 { return int64(id) } } + continue } @@ -476,5 +469,5 @@ func (app *App) GetAccessPoint(accessPointType string) (ap *AccessPoint, err err return point, nil } } - return nil, errors.Errorf("no access point of type %s found for app id %d", accessPointType, app.ID) + return nil, pkgerrors.Errorf("no access point of type %s found for app id %d", accessPointType, app.ID) } diff --git a/backend/server/database/model/app_test.go b/backend/server/database/model/app_test.go index ab42d799382d9010d93bae0852b69b116ad590b6..1e804d92c5c4afc4a23bcf18f874d37536658762 100644 --- a/backend/server/database/model/app_test.go +++ b/backend/server/database/model/app_test.go @@ -4,8 +4,6 @@ import ( "testing" require "github.com/stretchr/testify/require" - //log "github.com/sirupsen/logrus" - keaconfig "isc.org/stork/appcfg/kea" dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/database/model/common.go b/backend/server/database/model/common.go index ab8a3f5dd98d2d80067268ac918ad513d91cfcc0..e49cc204c63e2320169b8bd0d09ab58e53a28b48 100644 --- a/backend/server/database/model/common.go +++ b/backend/server/database/model/common.go @@ -2,6 +2,8 @@ package dbmodel import ( "strings" + + "github.com/go-pg/pg/v9" ) type SortDirEnum int @@ -35,3 +37,17 @@ func prepareOrderExpr(tableName string, sortField string, sortDir SortDirEnum) s } return orderExpr } + +// Convenience function which inserts new entry into a database or updates an +// existing entry. It determines whether this is new or existing entry by +// examining a value of the id parameter. The id is equal to 0 if this is +// a new entry. +func upsertInTransaction(tx *pg.Tx, id int64, model interface{}) (err error) { + if id == 0 { + _, err = tx.Model(model).Insert() + } else { + _, err = tx.Model(model).WherePK().Update() + } + + return err +} diff --git a/backend/server/database/model/daemon.go b/backend/server/database/model/daemon.go index c5c87e52ca2fd21c5d03d42f6f1a279cb8fc8fc5..50099a1dbb602062ca7a2aae6f8bebd7ffc3b028 100644 --- a/backend/server/database/model/daemon.go +++ b/backend/server/database/model/daemon.go @@ -3,11 +3,11 @@ package dbmodel import ( "context" "encoding/json" + "errors" "time" "github.com/go-pg/pg/v9" - "github.com/pkg/errors" - + pkgerrors "github.com/pkg/errors" keaconfig "isc.org/stork/appcfg/kea" dbops "isc.org/stork/server/database" ) @@ -247,10 +247,10 @@ func GetDaemonByID(db *pg.DB, id int64) (*Daemon, error) { q = q.Relation("App.Machine") q = q.Where("daemon.id = ?", id) err := q.Select() - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } else if err != nil { - return nil, errors.Wrapf(err, "problem with getting daemon %v", id) + return nil, pkgerrors.Wrapf(err, "problem with getting daemon %v", id) } return &app, nil } @@ -270,7 +270,7 @@ func UpdateDaemon(dbIface interface{}, daemon *Daemon) error { // Update common daemon instance. _, err = tx.Model(daemon).WherePK().Update() if err != nil { - return errors.Wrapf(err, "problem with updating daemon %d", daemon.ID) + return pkgerrors.Wrapf(err, "problem with updating daemon %d", daemon.ID) } // If this is a Kea daemon, we have to update Kea specific tables too. @@ -279,7 +279,7 @@ func UpdateDaemon(dbIface interface{}, daemon *Daemon) error { daemon.KeaDaemon.DaemonID = daemon.ID _, err = tx.Model(daemon.KeaDaemon).WherePK().Update() if err != nil { - return errors.Wrapf(err, "problem with updating general Kea specific information for daemon %d", + return pkgerrors.Wrapf(err, "problem with updating general Kea specific information for daemon %d", daemon.ID) } @@ -288,7 +288,7 @@ func UpdateDaemon(dbIface interface{}, daemon *Daemon) error { daemon.KeaDaemon.KeaDHCPDaemon.KeaDaemonID = daemon.KeaDaemon.ID _, err = tx.Model(daemon.KeaDaemon.KeaDHCPDaemon).WherePK().Update() if err != nil { - return errors.Wrapf(err, "problem with updating general Kea DHCP information for daemon %d", + return pkgerrors.Wrapf(err, "problem with updating general Kea DHCP information for daemon %d", daemon.ID) } } @@ -297,14 +297,14 @@ func UpdateDaemon(dbIface interface{}, daemon *Daemon) error { daemon.Bind9Daemon.DaemonID = daemon.ID _, err = tx.Model(daemon.Bind9Daemon).WherePK().Update() if err != nil { - return errors.Wrapf(err, "problem with updating Bind9 specific information for daemon %d", + return pkgerrors.Wrapf(err, "problem with updating Bind9 specific information for daemon %d", daemon.ID) } } err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing daemon %d after update", daemon.ID) + err = pkgerrors.WithMessagef(err, "problem with committing daemon %d after update", daemon.ID) } return err @@ -320,12 +320,12 @@ func (d *KeaDaemon) AfterScan(ctx context.Context) error { bytes, err := json.Marshal(d.Config) if err != nil { - return errors.Wrapf(err, "problem with marshalling Kea config: %+v ", *d.Config) + return pkgerrors.Wrapf(err, "problem with marshalling Kea config: %+v ", *d.Config) } err = json.Unmarshal(bytes, d.Config) if err != nil { - return errors.Wrapf(err, "problem with unmarshalling Kea config") + return pkgerrors.Wrapf(err, "problem with unmarshalling Kea config") } return nil } @@ -355,7 +355,7 @@ func (d *Daemon) SetConfig(config interface{}) error { if d.KeaDaemon != nil { parsedConfig, ok := config.(*KeaConfig) if !ok { - return errors.Errorf("error setting non Kea config for Kea daemon %s", d.Name) + return pkgerrors.Errorf("error setting non Kea config for Kea daemon %s", d.Name) } existingLogTargets := d.LogTargets diff --git a/backend/server/database/model/daemon_test.go b/backend/server/database/model/daemon_test.go index 379e87cc08628a397d492fecf4c401108b2c887d..7685821361ac872b21faa98b01ded4a34234468a 100644 --- a/backend/server/database/model/daemon_test.go +++ b/backend/server/database/model/daemon_test.go @@ -5,7 +5,6 @@ import ( "time" require "github.com/stretchr/testify/require" - dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/database/model/dhcp_test.go b/backend/server/database/model/dhcp_test.go index 985a50e9e7fb35f310bc90e37a52bd8ae78edc23..d6558474e0dae2fe21fd1abbc9925fb067055f8b 100644 --- a/backend/server/database/model/dhcp_test.go +++ b/backend/server/database/model/dhcp_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - dbops "isc.org/stork/server/database" ) diff --git a/backend/server/database/model/event.go b/backend/server/database/model/event.go index 8c6ce31860987e4223da54d61f69b8d3b21cd41c..56ec0068210b803e11e64bf92a506e1bff79ffd2 100644 --- a/backend/server/database/model/event.go +++ b/backend/server/database/model/event.go @@ -1,10 +1,11 @@ package dbmodel import ( + "errors" "time" "github.com/go-pg/pg/v9" - "github.com/pkg/errors" + pkgerrors "github.com/pkg/errors" ) // Event levels. @@ -37,7 +38,7 @@ type Event struct { func AddEvent(db *pg.DB, event *Event) error { err := db.Insert(event) if err != nil { - err = errors.Wrapf(err, "problem with inserting event %+v", event) + err = pkgerrors.Wrapf(err, "problem with inserting event %+v", event) } return err } @@ -56,7 +57,7 @@ func AddEvent(db *pg.DB, event *Event) error { // order is used. func GetEventsByPage(db *pg.DB, offset int64, limit int64, level int64, daemonType *string, appType *string, machineID *int64, userID *int64, sortField string, sortDir SortDirEnum) ([]Event, int64, error) { if limit == 0 { - return nil, 0, errors.New("limit should be greater than 0") + return nil, 0, pkgerrors.New("limit should be greater than 0") } var events []Event @@ -88,10 +89,10 @@ func GetEventsByPage(db *pg.DB, offset int64, limit int64, level int64, daemonTy total, err := q.SelectAndCount() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return []Event{}, 0, nil } - return nil, 0, errors.Wrapf(err, "problem with getting events") + return nil, 0, pkgerrors.Wrapf(err, "problem with getting events") } return events, int64(total), nil } diff --git a/backend/server/database/model/group.go b/backend/server/database/model/group.go index f16bef6a95073e15265e07b57244b22aabea421c..b5a74d496010ce1a4e4400df021d543b10a9c0bf 100644 --- a/backend/server/database/model/group.go +++ b/backend/server/database/model/group.go @@ -1,10 +1,11 @@ package dbmodel import ( + "errors" + "github.com/go-pg/pg/v9" "github.com/go-pg/pg/v9/orm" - "github.com/pkg/errors" - + pkgerrors "github.com/pkg/errors" dbops "isc.org/stork/server/database" ) @@ -52,10 +53,10 @@ func GetGroupsByPage(db *dbops.PgDB, offset, limit int64, filterText *string, so total, err := q.SelectAndCount() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return []SystemGroup{}, 0, nil } - err = errors.Wrapf(err, "error while fetching a list of groups from the database") + err = pkgerrors.Wrapf(err, "error while fetching a list of groups from the database") } return groups, int64(total), err diff --git a/backend/server/database/model/host.go b/backend/server/database/model/host.go index ef6a1a3fd2bf11ca7b90e071a05d4fdfa4e59ecf..a3177cc4152ab0e366e3e1e1e88ada0781be7825 100644 --- a/backend/server/database/model/host.go +++ b/backend/server/database/model/host.go @@ -3,13 +3,13 @@ package dbmodel import ( "bytes" "encoding/hex" + "errors" "strings" "time" "github.com/go-pg/pg/v9" "github.com/go-pg/pg/v9/orm" - errors "github.com/pkg/errors" - + pkgerrors "github.com/pkg/errors" dbops "isc.org/stork/server/database" storkutil "isc.org/stork/util" ) @@ -51,7 +51,7 @@ type Host struct { LocalHosts []LocalHost // This flag is used to indicate that some changes have been applied to - //the Host instance locally and that these changes should be applied in + // the Host instance locally and that these changes should be applied in // the database too. It also indicates that the new app should be // associated with the host upon the call to the CommitSubnetHostsIntoDB. UpdateOnCommit bool `pg:"-"` @@ -79,7 +79,7 @@ func addHostIdentifiers(tx *pg.Tx, host *Host) error { Set("value = EXCLUDED.value"). Insert() if err != nil { - err = errors.Wrapf(err, "problem with adding host identifier with type %s for host with id %d", + err = pkgerrors.Wrapf(err, "problem with adding host identifier with type %s for host with id %d", identifier.Type, host.ID) return err } @@ -97,7 +97,7 @@ func addIPReservations(tx *pg.Tx, host *Host) error { OnConflict("DO NOTHING"). Insert() if err != nil { - err = errors.Wrapf(err, "problem with adding IP reservation %s for host with id %d", + err = pkgerrors.Wrapf(err, "problem with adding IP reservation %s for host with id %d", reservation.Address, host.ID) return err } @@ -110,7 +110,7 @@ func addIPReservations(tx *pg.Tx, host *Host) error { func AddHost(dbIface interface{}, host *Host) error { tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for adding new host") + err = pkgerrors.WithMessagef(err, "problem with starting transaction for adding new host") return err } defer rollback() @@ -118,7 +118,7 @@ func AddHost(dbIface interface{}, host *Host) error { // Add the host and fetch its id. _, err = tx.Model(host).Insert() if err != nil { - err = errors.Wrapf(err, "problem with adding new host") + err = pkgerrors.Wrapf(err, "problem with adding new host") return err } @@ -137,7 +137,7 @@ func AddHost(dbIface interface{}, host *Host) error { // Everything is fine, commit the changes. err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing new host") + err = pkgerrors.WithMessagef(err, "problem with committing new host") } return err @@ -147,7 +147,7 @@ func AddHost(dbIface interface{}, host *Host) error { func UpdateHost(dbIface interface{}, host *Host) error { tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for updating host with id %d", + err = pkgerrors.WithMessagef(err, "problem with starting transaction for updating host with id %d", host.ID) return err } @@ -165,13 +165,13 @@ func UpdateHost(dbIface interface{}, host *Host) error { Where("host_identifier.type NOT IN (?)", pg.In(hostIDTypes)). Delete() if err != nil { - err = errors.Wrapf(err, "problem with deleting host identifiers for host %d", host.ID) + err = pkgerrors.Wrapf(err, "problem with deleting host identifiers for host %d", host.ID) return err } // Add or update host identifiers. err = addHostIdentifiers(tx, host) if err != nil { - return errors.WithMessagef(err, "problem with updating host with id %d", host.ID) + return pkgerrors.WithMessagef(err, "problem with updating host with id %d", host.ID) } // Delete all existing reservations for the host which are not present in @@ -187,26 +187,26 @@ func UpdateHost(dbIface interface{}, host *Host) error { Where("ip_reservation.address NOT IN (?)", pg.In(ipAddresses)). Delete() if err != nil { - err = errors.Wrapf(err, "problem with deleting IP reservations for host %d", host.ID) + err = pkgerrors.Wrapf(err, "problem with deleting IP reservations for host %d", host.ID) return err } // Add or update host reservations. err = addIPReservations(tx, host) if err != nil { - return errors.WithMessagef(err, "problem with updating host with id %d", host.ID) + return pkgerrors.WithMessagef(err, "problem with updating host with id %d", host.ID) } // Update the host information. _, err = tx.Model(host).WherePK().Update() if err != nil { - err = errors.Wrapf(err, "problem with updating host with id %d", host.ID) + err = pkgerrors.Wrapf(err, "problem with updating host with id %d", host.ID) return err } // Everything is fine. Commit the changes. err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing updated host with id %d", host.ID) + err = pkgerrors.WithMessagef(err, "problem with committing updated host with id %d", host.ID) } return err @@ -225,12 +225,11 @@ func GetHost(db *pg.DB, hostID int64) (*Host, error) { Relation("LocalHosts.App"). Where("host.id = ?", hostID). Select() - if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting a host with id %d", hostID) + err = pkgerrors.Wrapf(err, "problem with getting a host with id %d", hostID) return nil, err } return host, err @@ -261,12 +260,11 @@ func GetAllHosts(db *pg.DB, family int) ([]Host, error) { OrderExpr("id ASC") err := q.Select() - if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting all hosts for family %d", family) + err = pkgerrors.Wrapf(err, "problem with getting all hosts for family %d", family) return nil, err } return hosts, err @@ -274,13 +272,13 @@ func GetAllHosts(db *pg.DB, family int) ([]Host, error) { // Fetches a collection of hosts by subnet ID. This function may be sometimes // used within a transaction. In particular, when we're synchronizing hosts -// fetched from the Kea hosts backend in multiple chunks.` +// fetched from the Kea hosts backend in multiple chunks.`. func GetHostsBySubnetID(dbIface interface{}, subnetID int64) ([]Host, error) { hosts := []Host{} tx, rollback, _, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for getting hosts for subnet with id %d", subnetID) + err = pkgerrors.WithMessagef(err, "problem with starting transaction for getting hosts for subnet with id %d", subnetID) return hosts, err } defer rollback() @@ -308,10 +306,10 @@ func GetHostsBySubnetID(dbIface interface{}, subnetID int64) ([]Host, error) { err = q.Select() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting hosts by subnet ID %d", subnetID) + err = pkgerrors.Wrapf(err, "problem with getting hosts by subnet ID %d", subnetID) return nil, err } return hosts, err @@ -408,10 +406,10 @@ func GetHostsByPage(db *pg.DB, offset, limit int64, appID int64, subnetID *int64 total, err := q.SelectAndCount() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, 0, nil } - err = errors.Wrapf(err, "problem with getting hosts by page") + err = pkgerrors.Wrapf(err, "problem with getting hosts by page") } return hosts, int64(total), err } @@ -423,7 +421,7 @@ func DeleteHost(db *pg.DB, hostID int64) error { } _, err := db.Model(host).WherePK().Delete() if err != nil { - err = errors.Wrapf(err, "problem with deleting a host with id %d", hostID) + err = pkgerrors.Wrapf(err, "problem with deleting a host with id %d", hostID) } return err } @@ -440,7 +438,7 @@ func DeleteLocalHostsWithOtherSeq(db *pg.DB, seq int64, dataSource string) error } _, err := q.Delete() if err != nil { - err = errors.Wrapf(err, "problem with deleting associations between apps and hosts for sequence number %d and data source type %s", seq, dataSource) + err = pkgerrors.Wrapf(err, "problem with deleting associations between apps and hosts for sequence number %d and data source type %s", seq, dataSource) } return err } @@ -453,7 +451,7 @@ func DeleteLocalHostsWithOtherSeq(db *pg.DB, seq int64, dataSource string) error func AddAppToHost(dbIface interface{}, host *Host, app *App, source string, seq int64) error { tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for associating an app %d with the host %d", + err = pkgerrors.WithMessagef(err, "problem with starting transaction for associating an app %d with the host %d", app.ID, host.ID) return err } @@ -478,14 +476,14 @@ func AddAppToHost(dbIface interface{}, host *Host, app *App, source string, seq _, err = q.Insert() if err != nil { - err = errors.Wrapf(err, "problem with associating the app %d with the host %d", + err = pkgerrors.Wrapf(err, "problem with associating the app %d with the host %d", app.ID, host.ID) return err } err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing transaction associating the app %d with the host %d", + err = pkgerrors.WithMessagef(err, "problem with committing transaction associating the app %d with the host %d", app.ID, host.ID) } return err @@ -500,20 +498,20 @@ func commitHostsIntoDB(tx *pg.Tx, hosts []Host, subnetID int64, app *App, source if newHost { err = AddHost(tx, &hosts[i]) if err != nil { - err = errors.WithMessagef(err, "unable to add detected host to the database") + err = pkgerrors.WithMessagef(err, "unable to add detected host to the database") return err } } else if hosts[i].UpdateOnCommit { err = UpdateHost(tx, &hosts[i]) if err != nil { - err = errors.WithMessagef(err, "unable to update detected host in the database") + err = pkgerrors.WithMessagef(err, "unable to update detected host in the database") return err } } if newHost || hosts[i].UpdateOnCommit { err = AddAppToHost(tx, &hosts[i], app, source, seq) if err != nil { - err = errors.WithMessagef(err, "unable to associate detected host with Kea app having id %d", + err = pkgerrors.WithMessagef(err, "unable to associate detected host with Kea app having id %d", app.ID) return err } @@ -544,7 +542,7 @@ func CommitSubnetHostsIntoDB(tx *pg.Tx, subnet *Subnet, app *App, source string, func GetNextBulkUpdateSeq(db *dbops.PgDB) (seq int64, err error) { _, err = db.QueryOne(pg.Scan(&seq), "SELECT nextval('bulk_update_seq')") if err != nil { - err = errors.Wrapf(err, "problem with getting next bulk update sequence number") + err = pkgerrors.Wrapf(err, "problem with getting next bulk update sequence number") } return seq, err } diff --git a/backend/server/database/model/host_test.go b/backend/server/database/model/host_test.go index 874cce9e60a0020cf1871c02ad930d13a8c06d98..9ff96c22f193451befbca25ea2b2a08d7e328e72 100644 --- a/backend/server/database/model/host_test.go +++ b/backend/server/database/model/host_test.go @@ -5,7 +5,6 @@ import ( "github.com/go-pg/pg/v9" "github.com/stretchr/testify/require" - dbops "isc.org/stork/server/database" dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/database/model/indexedsubnets.go b/backend/server/database/model/indexedsubnets.go index a76ad84352befa19b6ab6155df7a7550fd57b240..06ecf2c7b144d4a019a249ede474e1a451a51abf 100644 --- a/backend/server/database/model/indexedsubnets.go +++ b/backend/server/database/model/indexedsubnets.go @@ -30,5 +30,6 @@ func (is *IndexedSubnets) Populate() bool { byPrefix[is.RandomAccess[i].Prefix] = &is.RandomAccess[i] } is.ByPrefix = byPrefix + return true } diff --git a/backend/server/database/model/kea_config.go b/backend/server/database/model/kea_config.go index ca9c8f88c9ef7d8e186a9fb1f2f8605345cab8e5..62f3b5c582027b4326a161057241ba778a46f815 100644 --- a/backend/server/database/model/kea_config.go +++ b/backend/server/database/model/kea_config.go @@ -8,7 +8,6 @@ import ( "github.com/mitchellh/mapstructure" "github.com/pkg/errors" - keaconfig "isc.org/stork/appcfg/kea" ) diff --git a/backend/server/database/model/kea_config_test.go b/backend/server/database/model/kea_config_test.go index cfe05bfc6b24af12c4b4058436c594a88d33782d..e98b75baee6f368acd51a3620728fb6091fb60df 100644 --- a/backend/server/database/model/kea_config_test.go +++ b/backend/server/database/model/kea_config_test.go @@ -4,7 +4,6 @@ import ( "testing" require "github.com/stretchr/testify/require" - keaconfig "isc.org/stork/appcfg/kea" ) diff --git a/backend/server/database/model/kea_subnet_test.go b/backend/server/database/model/kea_subnet_test.go index 51bf8a6adce70d570c9841ba86997bb1345ea4c8..336f844a56dda06fa123ffe7c1a7ba3df74285b9 100644 --- a/backend/server/database/model/kea_subnet_test.go +++ b/backend/server/database/model/kea_subnet_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - dbtest "isc.org/stork/server/database/test" ) @@ -30,45 +29,47 @@ func TestGetSubnetsByPageBasic(t *testing.T) { Type: AppTypeKea, Active: true, AccessPoints: accessPoints, - Daemons: []*Daemon{{ - KeaDaemon: &KeaDaemon{ - Config: NewKeaConfig(&map[string]interface{}{ - "Dhcp4": map[string]interface{}{ - "subnet4": []map[string]interface{}{{ - "id": 1, - "subnet": "192.168.0.0/24", - "pools": []map[string]interface{}{{ - "pool": "192.168.0.1-192.168.0.100", - }, { - "pool": "192.168.0.150-192.168.0.200", - }}, - }}, - "shared-networks": []map[string]interface{}{{ - "name": "frog", + Daemons: []*Daemon{ + { + KeaDaemon: &KeaDaemon{ + Config: NewKeaConfig(&map[string]interface{}{ + "Dhcp4": map[string]interface{}{ "subnet4": []map[string]interface{}{{ - "id": 11, - "subnet": "192.1.0.0/24", + "id": 1, + "subnet": "192.168.0.0/24", "pools": []map[string]interface{}{{ - "pool": "192.1.0.1-192.1.0.100", + "pool": "192.168.0.1-192.168.0.100", }, { - "pool": "192.1.0.150-192.1.0.200", + "pool": "192.168.0.150-192.168.0.200", }}, }}, - }, { - "name": "mouse", - "subnet4": []map[string]interface{}{{ - "id": 12, - "subnet": "192.2.0.0/24", - "pools": []map[string]interface{}{{ - "pool": "192.2.0.1-192.2.0.100", - }, { - "pool": "192.2.0.150-192.2.0.200", + "shared-networks": []map[string]interface{}{{ + "name": "frog", + "subnet4": []map[string]interface{}{{ + "id": 11, + "subnet": "192.1.0.0/24", + "pools": []map[string]interface{}{{ + "pool": "192.1.0.1-192.1.0.100", + }, { + "pool": "192.1.0.150-192.1.0.200", + }}, + }}, + }, { + "name": "mouse", + "subnet4": []map[string]interface{}{{ + "id": 12, + "subnet": "192.2.0.0/24", + "pools": []map[string]interface{}{{ + "pool": "192.2.0.1-192.2.0.100", + }, { + "pool": "192.2.0.150-192.2.0.200", + }}, }}, }}, - }}, - }, - }), - }}, + }, + }), + }, + }, }, } @@ -145,24 +146,26 @@ func TestGetSubnetsByPageBasic(t *testing.T) { Type: AppTypeKea, Active: true, AccessPoints: accessPoints, - Daemons: []*Daemon{{ - KeaDaemon: &KeaDaemon{ - Config: NewKeaConfig(&map[string]interface{}{ - "Dhcp6": map[string]interface{}{ - "subnet6": []map[string]interface{}{{ - "id": 2, - "subnet": "2001:db8:1::/64", - }}, - "shared-networks": []map[string]interface{}{{ - "name": "fox", + Daemons: []*Daemon{ + { + KeaDaemon: &KeaDaemon{ + Config: NewKeaConfig(&map[string]interface{}{ + "Dhcp6": map[string]interface{}{ "subnet6": []map[string]interface{}{{ - "id": 21, - "subnet": "5001:db8:1::/64", + "id": 2, + "subnet": "2001:db8:1::/64", }}, - }}, - }, - }), - }}, + "shared-networks": []map[string]interface{}{{ + "name": "fox", + "subnet6": []map[string]interface{}{{ + "id": 21, + "subnet": "5001:db8:1::/64", + }}, + }}, + }, + }), + }, + }, }, } _, err = AddApp(db, a6) @@ -513,7 +516,8 @@ func TestGetSharedNetworksByPageBasic(t *testing.T) { }}, }, }), - }}, + }, + }, }, } _, err = AddApp(db, a4) diff --git a/backend/server/database/model/log_target.go b/backend/server/database/model/log_target.go index 7a3406814e2b079829b45fa155cc0cb98e251628..856abe7db03acd2cc2e4a60de95b4718f177ddd7 100644 --- a/backend/server/database/model/log_target.go +++ b/backend/server/database/model/log_target.go @@ -1,10 +1,11 @@ package dbmodel import ( + "errors" "time" "github.com/go-pg/pg/v9" - "github.com/pkg/errors" + pkgerrors "github.com/pkg/errors" ) // A structure reflecting information about a logger used by a daemon. @@ -26,10 +27,10 @@ func GetLogTargetByID(db *pg.DB, id int64) (*LogTarget, error) { Relation("Daemon.App.Machine"). Where("log_target.id = ?", id). Select() - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } else if err != nil { - return nil, errors.Wrapf(err, "problem with getting log target with id %d", id) + return nil, pkgerrors.Wrapf(err, "problem with getting log target with id %d", id) } return &logTarget, nil } diff --git a/backend/server/database/model/log_target_test.go b/backend/server/database/model/log_target_test.go index 1b942490519c4438465107d3d869192e0b2e04c8..9bf8884991b18c435ac661c6515719f19af64d5e 100644 --- a/backend/server/database/model/log_target_test.go +++ b/backend/server/database/model/log_target_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/database/model/machine.go b/backend/server/database/model/machine.go index 2b1affde39fea412c75069a1ae4dab421a2d8193..e73ce3610c9617c769d1adef4b31de2ee503ee41 100644 --- a/backend/server/database/model/machine.go +++ b/backend/server/database/model/machine.go @@ -1,11 +1,12 @@ package dbmodel import ( + "errors" "time" "github.com/go-pg/pg/v9" "github.com/go-pg/pg/v9/orm" - "github.com/pkg/errors" + pkgerrors "github.com/pkg/errors" ) // Part of machine table in database that describes state of machine. In DB it is stored as JSONB. @@ -43,7 +44,7 @@ type Machine struct { func AddMachine(db *pg.DB, machine *Machine) error { err := db.Insert(machine) if err != nil { - err = errors.Wrapf(err, "problem with inserting machine %+v", machine) + err = pkgerrors.Wrapf(err, "problem with inserting machine %+v", machine) } return err } @@ -55,10 +56,10 @@ func GetMachineByAddressAndAgentPort(db *pg.DB, address string, agentPort int64) q = q.Where("agent_port = ?", agentPort) q = q.Relation("Apps.AccessPoints") err := q.Select() - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } else if err != nil { - return nil, errors.Wrapf(err, "problem with getting machine %s:%d", address, agentPort) + return nil, pkgerrors.Wrapf(err, "problem with getting machine %s:%d", address, agentPort) } return &machine, nil } @@ -70,22 +71,22 @@ func GetMachineByID(db *pg.DB, id int64) (*Machine, error) { q = q.Relation("Apps.Daemons.Bind9Daemon") q = q.Relation("Apps.AccessPoints") err := q.Select() - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } else if err != nil { - return nil, errors.Wrapf(err, "problem with getting machine %v", id) + return nil, pkgerrors.Wrapf(err, "problem with getting machine %v", id) } return &machine, nil } -func RefreshMachineFromDb(db *pg.DB, machine *Machine) error { +func RefreshMachineFromDB(db *pg.DB, machine *Machine) error { machine.Apps = []*App{} q := db.Model(machine).Where("id = ?", machine.ID) q = q.Relation("Apps.AccessPoints") err := q.Select() if err != nil { - return errors.Wrapf(err, "problem with getting machine %v", machine.ID) + return pkgerrors.Wrapf(err, "problem with getting machine %v", machine.ID) } return nil @@ -100,7 +101,7 @@ func RefreshMachineFromDb(db *pg.DB, machine *Machine) error { // order is used. func GetMachinesByPage(db *pg.DB, offset int64, limit int64, filterText *string, sortField string, sortDir SortDirEnum) ([]Machine, int64, error) { if limit == 0 { - return nil, 0, errors.New("limit should be greater than 0") + return nil, 0, pkgerrors.New("limit should be greater than 0") } var machines []Machine @@ -136,10 +137,10 @@ func GetMachinesByPage(db *pg.DB, offset int64, limit int64, filterText *string, total, err := q.SelectAndCount() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return []Machine{}, 0, nil } - return nil, 0, errors.Wrapf(err, "problem with getting machines") + return nil, 0, pkgerrors.Wrapf(err, "problem with getting machines") } return machines, int64(total), nil @@ -156,8 +157,8 @@ func GetAllMachines(db *pg.DB) ([]Machine, error) { q = q.Relation("Apps.Daemons.Bind9Daemon") err := q.Select() - if err != nil && err != pg.ErrNoRows { - return nil, errors.Wrapf(err, "problem with getting machines") + if err != nil && errors.Is(err, pg.ErrNoRows) { + return nil, pkgerrors.Wrapf(err, "problem with getting machines") } return machines, nil @@ -166,7 +167,7 @@ func GetAllMachines(db *pg.DB) ([]Machine, error) { func DeleteMachine(db *pg.DB, machine *Machine) error { err := db.Delete(machine) if err != nil { - return errors.Wrapf(err, "problem with deleting machine %v", machine.ID) + return pkgerrors.Wrapf(err, "problem with deleting machine %v", machine.ID) } return nil } diff --git a/backend/server/database/model/machine_test.go b/backend/server/database/model/machine_test.go index 7c04eaf6fa5f3d6be75943098c61f8f89c9e5c35..bcd095e66872973c9b54b0f07fcb69994acc9472 100644 --- a/backend/server/database/model/machine_test.go +++ b/backend/server/database/model/machine_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/stretchr/testify/require" - dbtest "isc.org/stork/server/database/test" ) @@ -344,7 +343,7 @@ func TestDeleteMachineWithApps(t *testing.T) { require.NotEqual(t, 0, appID) // reload machine from db to get apps relation loaded - err = RefreshMachineFromDb(db, m) + err = RefreshMachineFromDB(db, m) require.Nil(t, err) // delete machine @@ -357,7 +356,7 @@ func TestDeleteMachineWithApps(t *testing.T) { require.Nil(t, a) } -func TestRefreshMachineFromDb(t *testing.T) { +func TestRefreshMachineFromDB(t *testing.T) { db, _, teardown := dbtest.SetupDatabaseTestCase(t) defer teardown() @@ -378,7 +377,7 @@ func TestRefreshMachineFromDb(t *testing.T) { m.State.Cpus = 2 m.Error = "" - err = RefreshMachineFromDb(db, m) + err = RefreshMachineFromDB(db, m) require.Nil(t, err) require.Equal(t, "aaaa", m.State.Hostname) require.EqualValues(t, 4, m.State.Cpus) diff --git a/backend/server/database/model/pool.go b/backend/server/database/model/pool.go index 5271966e39dcbd10dac6986c1490063aaf6b027f..6ba0f4e4f081a0d24a2eed1feab8c81113354ed4 100644 --- a/backend/server/database/model/pool.go +++ b/backend/server/database/model/pool.go @@ -1,13 +1,13 @@ package dbmodel import ( - cidr "github.com/apparentlymart/go-cidr/cidr" - errors "github.com/pkg/errors" - dbops "isc.org/stork/server/database" - "net" "strings" "time" + + cidr "github.com/apparentlymart/go-cidr/cidr" + errors "github.com/pkg/errors" + dbops "isc.org/stork/server/database" ) // Reflects IPv4 or IPv6 address pool. diff --git a/backend/server/database/model/pool_test.go b/backend/server/database/model/pool_test.go index 6e8c5dff903b7603874f35be02a32247f42c0e71..2fe1365733beb103d878ba20565d323ac129812e 100644 --- a/backend/server/database/model/pool_test.go +++ b/backend/server/database/model/pool_test.go @@ -1,10 +1,10 @@ package dbmodel import ( + "testing" + "github.com/stretchr/testify/require" dbtest "isc.org/stork/server/database/test" - - "testing" ) // Test that the pool instance can be created from two addresses diff --git a/backend/server/database/model/rps_interval.go b/backend/server/database/model/rps_interval.go index c68e5d2e39dc2ecb5e08f7722c899f9b0b0965c3..2d25d596116ef64bfe32fe76f4e37db16534e7e9 100644 --- a/backend/server/database/model/rps_interval.go +++ b/backend/server/database/model/rps_interval.go @@ -7,7 +7,7 @@ import ( errors "github.com/pkg/errors" ) -// The number of responses a daemon sent during an interval of time +// The number of responses a daemon sent during an interval of time. type RpsInterval struct { KeaDaemonID int64 `pg:",pk"` // ID of Kea daemon StartTime time.Time `pg:",pk"` // beginning of this interval @@ -32,7 +32,7 @@ func GetAllRpsIntervals(db *pg.DB) ([]*RpsInterval, error) { // One element for the given daemon id where: // RpsInterval.StartTime = 0 (unused) // RpsInterval.Responses = total of number of responses -// RpsInterval.Duration = total of the interval durations +// RpsInterval.Duration = total of the interval durations. func GetTotalRpsOverIntervalForDaemon(db *pg.DB, startTime time.Time, endTime time.Time, daemonID int64) ([]*RpsInterval, error) { rpsTotals := []*RpsInterval{} @@ -51,7 +51,7 @@ func GetTotalRpsOverIntervalForDaemon(db *pg.DB, startTime time.Time, endTime ti return rpsTotals, nil } -// Add an interval to the database +// Add an interval to the database. func AddRpsInterval(db *pg.DB, rpsInterval *RpsInterval) error { err := db.Insert(rpsInterval) if err != nil { @@ -60,7 +60,7 @@ func AddRpsInterval(db *pg.DB, rpsInterval *RpsInterval) error { return err } -// Delete all records whose start_time is older than a given time +// Delete all records whose start_time is older than a given time. func AgeOffRpsInterval(db *pg.DB, startTime time.Time) error { // Delete records. _, err := db.Model(&RpsInterval{}).Where("start_time < ?", startTime).Delete() diff --git a/backend/server/database/model/service.go b/backend/server/database/model/service.go index a804c01c2e41e0cc9a260359d54b5c2ea5e8cfdd..b78a3d13ca0b69784663204abe3e17f254afef59 100644 --- a/backend/server/database/model/service.go +++ b/backend/server/database/model/service.go @@ -1,12 +1,12 @@ package dbmodel import ( - "github.com/go-pg/pg/v9" - "github.com/pkg/errors" + "errors" + "time" + "github.com/go-pg/pg/v9" + pkgerrors "github.com/pkg/errors" dbops "isc.org/stork/server/database" - - "time" ) // A structure reflecting service SQL table. This table holds @@ -89,7 +89,7 @@ func addServiceDaemons(dbIface interface{}, service *BaseService) (err error) { tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessage(err, "problem with starting transaction for adding daemons to a service") + err = pkgerrors.WithMessage(err, "problem with starting transaction for adding daemons to a service") } defer rollback() @@ -108,7 +108,7 @@ func addServiceDaemons(dbIface interface{}, service *BaseService) (err error) { // changes. err = commit() if err != nil { - err = errors.WithMessage(err, "problem with committing associations of daemon with the service") + err = pkgerrors.WithMessage(err, "problem with committing associations of daemon with the service") } return err @@ -118,7 +118,7 @@ func addServiceDaemons(dbIface interface{}, service *BaseService) (err error) { func AddDaemonToService(dbIface interface{}, serviceID int64, daemon *Daemon) error { tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for associating a daemon %d with the service %d", + err = pkgerrors.WithMessagef(err, "problem with starting transaction for associating a daemon %d with the service %d", daemon.ID, serviceID) return err } @@ -130,14 +130,14 @@ func AddDaemonToService(dbIface interface{}, serviceID int64, daemon *Daemon) er service.Daemons = append(service.Daemons, daemon) err = addServiceDaemons(tx, service) if err != nil { - err = errors.Wrapf(err, "problem with associating a daemon having id %d with service %d", + err = pkgerrors.Wrapf(err, "problem with associating a daemon having id %d with service %d", daemon.ID, serviceID) return err } err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing transaction associating daemon %d with the service %d", + err = pkgerrors.WithMessagef(err, "problem with committing transaction associating daemon %d with the service %d", daemon.ID, service.ID) } return err @@ -152,8 +152,8 @@ func DeleteDaemonFromService(db *pg.DB, serviceID, daemonID int64) (bool, error) ServiceID: serviceID, } rows, err := db.Model(as).WherePK().Delete() - if err != nil && err != pg.ErrNoRows { - err = errors.Wrapf(err, "problem with deleting a daemon with id %d from the service %d", + if err != nil && !errors.Is(err, pg.ErrNoRows) { + err = pkgerrors.Wrapf(err, "problem with deleting a daemon with id %d from the service %d", daemonID, serviceID) return false, err } @@ -166,7 +166,7 @@ func DeleteDaemonFromService(db *pg.DB, serviceID, daemonID int64) (bool, error) func AddService(dbIface interface{}, service *Service) error { tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for adding new service") + err = pkgerrors.WithMessagef(err, "problem with starting transaction for adding new service") return err } defer rollback() @@ -174,14 +174,14 @@ func AddService(dbIface interface{}, service *Service) error { // Insert generic information into the service table. _, err = tx.Model(service).Insert() if err != nil { - err = errors.Wrapf(err, "problem with adding new service") + err = pkgerrors.Wrapf(err, "problem with adding new service") return err } // Add associations of the daemons with the service. err = addServiceDaemons(tx, &service.BaseService) if err != nil { - err = errors.Wrapf(err, "problem with associating daemons with a new service") + err = pkgerrors.Wrapf(err, "problem with associating daemons with a new service") return err } @@ -197,7 +197,7 @@ func AddService(dbIface interface{}, service *Service) error { // All ok, let's commit the changes. err = commit() if err != nil { - err = errors.WithMessage(err, "problem with committing new service into the database") + err = pkgerrors.WithMessage(err, "problem with committing new service into the database") } return err @@ -215,13 +215,13 @@ func AddHAService(dbIface interface{}, serviceID int64, haService *BaseHAService _, err = tx.Model(haService).Insert() if err != nil { - err = errors.Wrapf(err, "problem with adding new HA service to the database") + err = pkgerrors.Wrapf(err, "problem with adding new HA service to the database") return err } err = commit() if err != nil { - err = errors.WithMessage(err, "problem with committing new HA service into the database") + err = pkgerrors.WithMessage(err, "problem with committing new HA service into the database") } return err } @@ -237,13 +237,13 @@ func UpdateBaseService(dbIface interface{}, service *BaseService) error { err = tx.Update(service) if err != nil { - err = errors.Wrapf(err, "problem with updating base service with id %d", service.ID) + err = pkgerrors.Wrapf(err, "problem with updating base service with id %d", service.ID) return err } err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing base service %d information after update", + err = pkgerrors.WithMessagef(err, "problem with committing base service %d information after update", service.ID) } return err @@ -260,14 +260,14 @@ func UpdateBaseHAService(dbIface interface{}, service *BaseHAService) error { err = tx.Update(service) if err != nil { - err = errors.Wrapf(err, "problem with updating the HA information for service with id %d", + err = pkgerrors.Wrapf(err, "problem with updating the HA information for service with id %d", service.ServiceID) return err } err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing HA information for service with id %d after update", + err = pkgerrors.WithMessagef(err, "problem with committing HA information for service with id %d after update", service.ServiceID) } return err @@ -299,7 +299,7 @@ func UpdateService(dbIface interface{}, service *Service) error { err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing service with id %d after update", service.ID) + err = pkgerrors.WithMessagef(err, "problem with committing service with id %d after update", service.ID) } return err } @@ -313,12 +313,11 @@ func GetDetailedService(db *dbops.PgDB, serviceID int64) (*Service, error) { Relation("Daemons.App"). Where("service.id = ?", serviceID). Select() - if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting a service with id %d", serviceID) + err = pkgerrors.Wrapf(err, "problem with getting a service with id %d", serviceID) return nil, err } return service, err @@ -340,8 +339,8 @@ func GetDetailedServicesByAppID(db *dbops.PgDB, appID int64) ([]Service, error) OrderExpr("service.id ASC"). Select() - if err != nil && err != pg.ErrNoRows { - err = errors.Wrapf(err, "problem with getting services for app id %d", appID) + if err != nil && !errors.Is(err, pg.ErrNoRows) { + err = pkgerrors.Wrapf(err, "problem with getting services for app id %d", appID) return services, err } @@ -359,8 +358,8 @@ func GetDetailedAllServices(db *dbops.PgDB) ([]Service, error) { OrderExpr("id ASC"). Select() - if err != nil && err != pg.ErrNoRows { - err = errors.Wrapf(err, "problem with getting all services") + if err != nil && !errors.Is(err, pg.ErrNoRows) { + err = pkgerrors.Wrapf(err, "problem with getting all services") return services, err } return services, nil @@ -376,7 +375,7 @@ func DeleteService(db *dbops.PgDB, serviceID int64) error { } _, err := db.Model(service).WherePK().Delete() if err != nil { - err = errors.Wrapf(err, "problem with deleting the service having id %d", serviceID) + err = pkgerrors.Wrapf(err, "problem with deleting the service having id %d", serviceID) } return err } @@ -398,14 +397,14 @@ func CommitServicesIntoDB(dbIface interface{}, services []Service, daemon *Daemo err = UpdateService(tx, &services[i]) } if err != nil { - err = errors.WithMessagef(err, "problem with committing services into the database") + err = pkgerrors.WithMessagef(err, "problem with committing services into the database") return err } // Try to associate the app with the service. If the association already // exists this is no-op. err = AddDaemonToService(tx, services[i].ID, daemon) if err != nil { - err = errors.WithMessagef(err, "problem with associating detected service %d with daemon having id %d", + err = pkgerrors.WithMessagef(err, "problem with associating detected service %d with daemon having id %d", services[i].ID, daemon.ID) return err } @@ -413,7 +412,7 @@ func CommitServicesIntoDB(dbIface interface{}, services []Service, daemon *Daemo err = commit() if err != nil { - err = errors.WithMessage(err, "problem with committing services into the database") + err = pkgerrors.WithMessage(err, "problem with committing services into the database") } return err } diff --git a/backend/server/database/model/service_test.go b/backend/server/database/model/service_test.go index a391cef1f6816391969b3f9df20e40682dd467f2..0c11ecf4b46246d0370efa88cc41165e005d7ded 100644 --- a/backend/server/database/model/service_test.go +++ b/backend/server/database/model/service_test.go @@ -39,7 +39,7 @@ func accessPointArraysMatch(pts1, pts2 []*AccessPoint) bool { return true } - var found = make([]bool, len(pts1)) + found := make([]bool, len(pts1)) for i := 0; i < len(pts1); i++ { for j := 0; j < len(pts2); j++ { @@ -119,7 +119,7 @@ func daemonArraysMatch(daemonArray1, daemonArray2 []*Daemon) bool { return true } - var found = make([]bool, len(daemonArray1)) + found := make([]bool, len(daemonArray1)) for i := 0; i < len(daemonArray1); i++ { for j := 0; j < len(daemonArray2); j++ { diff --git a/backend/server/database/model/setting.go b/backend/server/database/model/setting.go index 94be000fb68fcf215fa24629db1298a079f936ad..50ec668c34373476984a220a893e2a5e00c7199c 100644 --- a/backend/server/database/model/setting.go +++ b/backend/server/database/model/setting.go @@ -1,10 +1,11 @@ package dbmodel import ( + "errors" "strconv" "github.com/go-pg/pg/v9" - "github.com/pkg/errors" + pkgerrors "github.com/pkg/errors" ) // This module provides global settings that can be used anywhere in the code. @@ -17,10 +18,12 @@ import ( // TODO: add caching to avoid trips to database; candidate caching libs: // https://allegro.tech/2016/03/writing-fast-cache-service-in-go.html -const SettingValTypeInt = 1 -const SettingValTypeBool = 2 -const SettingValTypeStr = 3 -const SettingValTypePasswd = 4 +const ( + SettingValTypeInt = 1 + SettingValTypeBool = 2 + SettingValTypeStr = 3 + SettingValTypePasswd = 4 +) // Represents a setting held in setting table in the database. type Setting struct { @@ -74,7 +77,7 @@ func InitializeSettings(db *pg.DB) error { // Check if there are new settings vs existing ones. Add new ones to DB. _, err := db.Model(&defaultSettings).OnConflict("DO NOTHING").Insert() if err != nil { - err = errors.Wrapf(err, "problem with inserting default settings") + err = pkgerrors.Wrapf(err, "problem with inserting default settings") } return err } @@ -84,10 +87,10 @@ func GetSetting(db *pg.DB, name string) (*Setting, error) { setting := Setting{} q := db.Model(&setting).Where("setting.name = ?", name) err := q.Select() - if err == pg.ErrNoRows { - return nil, errors.Wrapf(err, "setting %s is missing", name) + if errors.Is(err, pg.ErrNoRows) { + return nil, pkgerrors.Wrapf(err, "setting %s is missing", name) } else if err != nil { - return nil, errors.Wrapf(err, "problem with getting setting %s", name) + return nil, pkgerrors.Wrapf(err, "problem with getting setting %s", name) } return &setting, nil } @@ -99,7 +102,7 @@ func getAndCheckSetting(db *pg.DB, name string, expValType int64) (*Setting, err return nil, err } if s.ValType != expValType { - return nil, errors.Errorf("not matching setting type of %s (%d vs %d expected)", name, s.ValType, expValType) + return nil, pkgerrors.Errorf("not matching setting type of %s (%d vs %d expected)", name, s.ValType, expValType) } return s, nil } @@ -154,7 +157,7 @@ func GetAllSettings(db *pg.DB) (map[string]interface{}, error) { q := db.Model(&settings) err := q.Select() if err != nil { - return nil, errors.Wrapf(err, "problem with getting all settings") + return nil, pkgerrors.Wrapf(err, "problem with getting all settings") } settingsMap := make(map[string]interface{}) @@ -164,13 +167,13 @@ func GetAllSettings(db *pg.DB) (map[string]interface{}, error) { case SettingValTypeInt: val, err := strconv.ParseInt(s.Value, 10, 64) if err != nil { - return nil, errors.Wrapf(err, "problem with getting setting value of %s", s.Name) + return nil, pkgerrors.Wrapf(err, "problem with getting setting value of %s", s.Name) } settingsMap[s.Name] = val case SettingValTypeBool: val, err := strconv.ParseBool(s.Value) if err != nil { - return nil, errors.Wrapf(err, "problem with getting setting value of %s", s.Name) + return nil, pkgerrors.Wrapf(err, "problem with getting setting value of %s", s.Name) } settingsMap[s.Name] = val case SettingValTypeStr: @@ -192,7 +195,7 @@ func SetSettingInt(db *pg.DB, name string, value int64) error { s.Value = strconv.FormatInt(value, 10) err = db.Update(s) if err != nil { - return errors.Wrapf(err, "problem with updating setting %s", name) + return pkgerrors.Wrapf(err, "problem with updating setting %s", name) } return nil } @@ -206,7 +209,7 @@ func SetSettingBool(db *pg.DB, name string, value bool) error { s.Value = strconv.FormatBool(value) err = db.Update(s) if err != nil { - return errors.Wrapf(err, "problem with updating setting %s", name) + return pkgerrors.Wrapf(err, "problem with updating setting %s", name) } return nil } @@ -220,7 +223,7 @@ func SetSettingStr(db *pg.DB, name string, value string) error { s.Value = value err = db.Update(s) if err != nil { - return errors.Wrapf(err, "problem with updating setting %s", name) + return pkgerrors.Wrapf(err, "problem with updating setting %s", name) } return nil } @@ -234,7 +237,7 @@ func SetSettingPasswd(db *pg.DB, name string, value string) error { s.Value = value err = db.Update(s) if err != nil { - return errors.Wrapf(err, "problem with updating setting %s", name) + return pkgerrors.Wrapf(err, "problem with updating setting %s", name) } return nil } diff --git a/backend/server/database/model/setting_test.go b/backend/server/database/model/setting_test.go index 73e6709e88275c7638261fa676330e0594dc9a69..984cf5cc371c1159490d7f10ea1ca0771c30e49c 100644 --- a/backend/server/database/model/setting_test.go +++ b/backend/server/database/model/setting_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/database/model/shared_network.go b/backend/server/database/model/shared_network.go index 192f7e728c2ef20b85a686a8db221b7cf42be44f..4bf6b0d5750ba144ed9461adeb8e59286c443dc9 100644 --- a/backend/server/database/model/shared_network.go +++ b/backend/server/database/model/shared_network.go @@ -1,12 +1,12 @@ package dbmodel import ( + "errors" "time" "github.com/go-pg/pg/v9" "github.com/go-pg/pg/v9/orm" - errors "github.com/pkg/errors" - + pkgerrors "github.com/pkg/errors" dbops "isc.org/stork/server/database" ) @@ -29,7 +29,7 @@ type SharedNetwork struct { func AddSharedNetwork(dbIface interface{}, network *SharedNetwork) error { tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for adding new shared network with name %s", + err = pkgerrors.WithMessagef(err, "problem with starting transaction for adding new shared network with name %s", network.Name) return err } @@ -37,7 +37,7 @@ func AddSharedNetwork(dbIface interface{}, network *SharedNetwork) error { err = tx.Insert(network) if err != nil { - err = errors.Wrapf(err, "problem with adding new shared network %s into the database", network.Name) + err = pkgerrors.Wrapf(err, "problem with adding new shared network %s into the database", network.Name) return err } @@ -54,7 +54,7 @@ func AddSharedNetwork(dbIface interface{}, network *SharedNetwork) error { err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing new shared network with name %s into the database", + err = pkgerrors.WithMessagef(err, "problem with committing new shared network with name %s into the database", network.Name) } @@ -66,7 +66,7 @@ func AddSharedNetwork(dbIface interface{}, network *SharedNetwork) error { func UpdateSharedNetwork(dbIface interface{}, network *SharedNetwork) error { tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for updating shared network with name %s", + err = pkgerrors.WithMessagef(err, "problem with starting transaction for updating shared network with name %s", network.Name) return err } @@ -74,13 +74,13 @@ func UpdateSharedNetwork(dbIface interface{}, network *SharedNetwork) error { err = tx.Update(network) if err != nil { - err = errors.Wrapf(err, "problem with updating the shared network with id %d", network.ID) + err = pkgerrors.Wrapf(err, "problem with updating the shared network with id %d", network.ID) return err } err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing updates to shared network with name %s into the database", + err = pkgerrors.WithMessagef(err, "problem with committing updates to shared network with name %s into the database", network.Name) } return err @@ -99,12 +99,11 @@ func GetAllSharedNetworks(db *dbops.PgDB, family int) ([]SharedNetwork, error) { q = q.OrderExpr("id ASC") err := q.Select() - if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return []SharedNetwork{}, nil } - err = errors.Wrapf(err, "problem with getting all shared networks") + err = pkgerrors.Wrapf(err, "problem with getting all shared networks") return nil, err } return networks, err @@ -116,12 +115,11 @@ func GetSharedNetwork(db *dbops.PgDB, networkID int64) (*SharedNetwork, error) { err := db.Model(network). Where("shared_network.id = ?", networkID). Select() - if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting a shared network with id %d", networkID) + err = pkgerrors.Wrapf(err, "problem with getting a shared network with id %d", networkID) return nil, err } return network, err @@ -143,10 +141,10 @@ func GetSharedNetworkWithSubnets(db *dbops.PgDB, networkID int64) (network *Shar Select() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting a shared network with id %d and its subnets", networkID) + err = pkgerrors.Wrapf(err, "problem with getting a shared network with id %d and its subnets", networkID) return nil, err } return network, err @@ -159,7 +157,7 @@ func DeleteSharedNetwork(db *dbops.PgDB, networkID int64) error { } _, err := db.Model(network).WherePK().Delete() if err != nil { - err = errors.Wrapf(err, "problem with deleting the shared network with id %d", networkID) + err = pkgerrors.Wrapf(err, "problem with deleting the shared network with id %d", networkID) } return err } @@ -168,7 +166,7 @@ func DeleteSharedNetwork(db *dbops.PgDB, networkID int64) error { func DeleteSharedNetworkWithSubnets(db *dbops.PgDB, networkID int64) error { tx, err := db.Begin() if err != nil { - err = errors.Wrapf(err, "problem with starting transaction for deleting shared network with id %d and its subnets", + err = pkgerrors.Wrapf(err, "problem with starting transaction for deleting shared network with id %d and its subnets", networkID) return err } @@ -182,7 +180,7 @@ func DeleteSharedNetworkWithSubnets(db *dbops.PgDB, networkID int64) error { Where("subnet.shared_network_id = ?", networkID). Delete() if err != nil { - err = errors.Wrapf(err, "problem with deleting subnets from the shared network with id %d", networkID) + err = pkgerrors.Wrapf(err, "problem with deleting subnets from the shared network with id %d", networkID) return err } @@ -193,13 +191,13 @@ func DeleteSharedNetworkWithSubnets(db *dbops.PgDB, networkID int64) error { } _, err = db.Model(network).WherePK().Delete() if err != nil { - err = errors.Wrapf(err, "problem with deleting the shared network with id %d", networkID) + err = pkgerrors.Wrapf(err, "problem with deleting the shared network with id %d", networkID) return err } err = tx.Commit() if err != nil { - err = errors.Wrapf(err, "problem with committing deleted shared network with id %d", + err = pkgerrors.Wrapf(err, "problem with committing deleted shared network with id %d", networkID) } return err @@ -278,10 +276,10 @@ func GetSharedNetworksByPage(db *pg.DB, offset, limit, appID, family int64, filt // This returns the limited results plus the total number of records. total, err := q.SelectAndCount() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, 0, nil } - err = errors.Wrapf(err, "problem with getting shared networks by page") + err = pkgerrors.Wrapf(err, "problem with getting shared networks by page") } return networks, int64(total), err } @@ -298,7 +296,7 @@ func UpdateUtilizationInSharedNetwork(db *pg.DB, sharedNetworkID int64, addrUtil q = q.WherePK() _, err := q.Update() if err != nil { - err = errors.Wrapf(err, "problem with updating utilization in the shared network: %d", + err = pkgerrors.Wrapf(err, "problem with updating utilization in the shared network: %d", sharedNetworkID) } return err diff --git a/backend/server/database/model/shared_network_test.go b/backend/server/database/model/shared_network_test.go index 77cef604e1f30130a5fabd9c43c527342d48c8ff..3f73e01d9c53b1bccf354cc1f4086a61cb82fd48 100644 --- a/backend/server/database/model/shared_network_test.go +++ b/backend/server/database/model/shared_network_test.go @@ -1,10 +1,10 @@ package dbmodel import ( + "testing" + "github.com/stretchr/testify/require" dbtest "isc.org/stork/server/database/test" - - "testing" ) // Tests that the shared network can be added and retrieved. diff --git a/backend/server/database/model/stats_test.go b/backend/server/database/model/stats_test.go index 2ba56d6b55ebdb76291e6768adadc67476094993..d268dcc9d8a9f1cc593c89417ef7dd2d320b684c 100644 --- a/backend/server/database/model/stats_test.go +++ b/backend/server/database/model/stats_test.go @@ -4,8 +4,6 @@ import ( "testing" require "github.com/stretchr/testify/require" - //log "github.com/sirupsen/logrus" - dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/database/model/subnet.go b/backend/server/database/model/subnet.go index cf7b529595b17411795240e2c4d0c543ba3332f4..cb0c9807dfa831f64d99a62f2173ee52b317bc2a 100644 --- a/backend/server/database/model/subnet.go +++ b/backend/server/database/model/subnet.go @@ -2,13 +2,13 @@ package dbmodel import ( "context" + "errors" "strings" "time" "github.com/go-pg/pg/v9" "github.com/go-pg/pg/v9/orm" - errors "github.com/pkg/errors" - + pkgerrors "github.com/pkg/errors" dbops "isc.org/stork/server/database" storkutil "isc.org/stork/util" ) @@ -91,7 +91,7 @@ func addSubnetPools(dbIface interface{}, subnet *Subnet) (err error) { // use the existing transaction or start the new one. tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for adding pools to subnet with id %d", + err = pkgerrors.WithMessagef(err, "problem with starting transaction for adding pools to subnet with id %d", subnet.ID) } defer rollback() @@ -102,7 +102,7 @@ func addSubnetPools(dbIface interface{}, subnet *Subnet) (err error) { pool.SubnetID = subnet.ID _, err = tx.Model(&pool).OnConflict("DO NOTHING").Insert() if err != nil { - err = errors.Wrapf(err, "problem with adding an address pool %s-%s for subnet with id %d", + err = pkgerrors.Wrapf(err, "problem with adding an address pool %s-%s for subnet with id %d", pool.LowerBound, pool.UpperBound, subnet.ID) return err } @@ -114,7 +114,7 @@ func addSubnetPools(dbIface interface{}, subnet *Subnet) (err error) { pool.SubnetID = subnet.ID _, err = tx.Model(&pool).OnConflict("DO NOTHING").Insert() if err != nil { - err = errors.Wrapf(err, "problem with adding a prefix pool %s for subnet with id %d", + err = pkgerrors.Wrapf(err, "problem with adding a prefix pool %s for subnet with id %d", pool.Prefix, subnet.ID) return err } @@ -123,7 +123,7 @@ func addSubnetPools(dbIface interface{}, subnet *Subnet) (err error) { err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing pools into a subnet with id %d", subnet.ID) + err = pkgerrors.WithMessagef(err, "problem with committing pools into a subnet with id %d", subnet.ID) } return err @@ -134,7 +134,7 @@ func addSubnetWithPools(tx *pg.Tx, subnet *Subnet) error { // Add the subnet first. _, err := tx.Model(subnet).Insert() if err != nil { - err = errors.Wrapf(err, "problem with adding new subnet with prefix %s", subnet.Prefix) + err = pkgerrors.Wrapf(err, "problem with adding new subnet with prefix %s", subnet.Prefix) return err } @@ -152,7 +152,7 @@ func addSubnetWithPools(tx *pg.Tx, subnet *Subnet) error { func AddSubnet(dbIface interface{}, subnet *Subnet) error { tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for adding new subnet with prefix %s", + err = pkgerrors.WithMessagef(err, "problem with starting transaction for adding new subnet with prefix %s", subnet.Prefix) return err } @@ -164,7 +164,7 @@ func AddSubnet(dbIface interface{}, subnet *Subnet) error { } err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing new subnet with prefix %s into the database", + err = pkgerrors.WithMessagef(err, "problem with committing new subnet with prefix %s into the database", subnet.Prefix) } @@ -185,12 +185,11 @@ func GetSubnet(db *pg.DB, subnetID int64) (*Subnet, error) { Relation("LocalSubnets.App.AccessPoints"). Where("subnet.id = ?", subnetID). Select() - if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting a subnet with id %d", subnetID) + err = pkgerrors.Wrapf(err, "problem with getting a subnet with id %d", subnetID) return nil, err } return subnet, err @@ -220,10 +219,10 @@ func GetSubnetsByLocalID(db *pg.DB, localSubnetID int64, appID int64, family int } err := q.Select() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting subnets by local subnet id %d and app id %d", localSubnetID, appID) + err = pkgerrors.Wrapf(err, "problem with getting subnets by local subnet id %d and app id %d", localSubnetID, appID) return nil, err } return subnets, err @@ -253,10 +252,10 @@ func GetSubnetsByAppID(db *pg.DB, appID int64, family int) ([]Subnet, error) { } err := q.Select() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting subnets by app id %d", appID) + err = pkgerrors.Wrapf(err, "problem with getting subnets by app id %d", appID) return nil, err } return subnets, err @@ -276,12 +275,11 @@ func GetSubnetsByPrefix(db *pg.DB, prefix string) ([]Subnet, error) { Relation("LocalSubnets.App.AccessPoints"). Where("subnet.prefix = ?", prefix). Select() - if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting subnets with prefix %s", prefix) + err = pkgerrors.Wrapf(err, "problem with getting subnets with prefix %s", prefix) return nil, err } return subnets, err @@ -308,12 +306,11 @@ func GetAllSubnets(db *pg.DB, family int) ([]Subnet, error) { q = q.Where("family(subnet.prefix) = ?", family) } err := q.Select() - if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting all subnets for family %d", family) + err = pkgerrors.Wrapf(err, "problem with getting all subnets for family %d", family) return nil, err } return subnets, err @@ -389,15 +386,15 @@ func GetSubnetsByPage(db *pg.DB, offset, limit, appID, family int64, filterText // This returns the limited results plus the total number of records. total, err := q.SelectAndCount() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, 0, nil } - err = errors.Wrapf(err, "problem with getting subnets by page") + err = pkgerrors.Wrapf(err, "problem with getting subnets by page") } return subnets, int64(total), err } -// Get list of Subnets with LocalSubnets ordered by SharedNetworkID +// Get list of Subnets with LocalSubnets ordered by SharedNetworkID. func GetSubnetsWithLocalSubnets(db *pg.DB) ([]*Subnet, error) { subnets := []*Subnet{} q := db.Model(&subnets) @@ -408,10 +405,10 @@ func GetSubnetsWithLocalSubnets(db *pg.DB) ([]*Subnet, error) { err := q.Select() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrap(err, "problem with getting all subnets") + err = pkgerrors.Wrap(err, "problem with getting all subnets") return nil, err } return subnets, nil @@ -424,7 +421,7 @@ func GetSubnetsWithLocalSubnets(db *pg.DB) ([]*Subnet, error) { func AddAppToSubnet(dbIface interface{}, subnet *Subnet, app *App) error { tx, rollback, commit, err := dbops.Transaction(dbIface) if err != nil { - err = errors.WithMessagef(err, "problem with starting transaction for associating an app with id %d with the subnet %s", + err = pkgerrors.WithMessagef(err, "problem with starting transaction for associating an app with id %d with the subnet %s", app.ID, subnet.Prefix) return err } @@ -453,14 +450,14 @@ func AddAppToSubnet(dbIface interface{}, subnet *Subnet, app *App) error { Set("local_subnet_id = EXCLUDED.local_subnet_id"). Insert() if err != nil { - err = errors.Wrapf(err, "problem with associating the app with id %d with the subnet %s", + err = pkgerrors.Wrapf(err, "problem with associating the app with id %d with the subnet %s", app.ID, subnet.Prefix) return err } err = commit() if err != nil { - err = errors.WithMessagef(err, "problem with committing transaction associating the app with id %d with the subnet %s", + err = pkgerrors.WithMessagef(err, "problem with committing transaction associating the app with id %d with the subnet %s", app.ID, subnet.Prefix) } return err @@ -475,8 +472,8 @@ func DeleteAppFromSubnet(db *pg.DB, subnetID int64, appID int64) (bool, error) { SubnetID: subnetID, } rows, err := db.Model(localSubnet).WherePK().Delete() - if err != nil && err != pg.ErrNoRows { - err = errors.Wrapf(err, "problem with deleting an app with id %d from the subnet with %d", + if err != nil && !errors.Is(err, pg.ErrNoRows) { + err = pkgerrors.Wrapf(err, "problem with deleting an app with id %d from the subnet with %d", appID, subnetID) return false, err } @@ -504,7 +501,7 @@ func commitSubnetsIntoDB(tx *pg.Tx, networkID int64, subnets []Subnet, app *App, subnet.SharedNetworkID = networkID err = AddSubnet(tx, subnet) if err != nil { - err = errors.WithMessagef(err, "unable to add detected subnet %s to the database", + err = pkgerrors.WithMessagef(err, "unable to add detected subnet %s to the database", subnet.Prefix) return nil, err } @@ -512,7 +509,7 @@ func commitSubnetsIntoDB(tx *pg.Tx, networkID int64, subnets []Subnet, app *App, } err = AddAppToSubnet(tx, subnet, app) if err != nil { - err = errors.WithMessagef(err, "unable to associate detected subnet %s with Kea app having id %d", subnet.Prefix, app.ID) + err = pkgerrors.WithMessagef(err, "unable to associate detected subnet %s with Kea app having id %d", subnet.Prefix, app.ID) return nil, err } @@ -544,7 +541,7 @@ func CommitNetworksIntoDB(dbIface interface{}, networks []SharedNetwork, subnets // This is new shared network. Add it to the database. err = AddSharedNetwork(tx, network) if err != nil { - err = errors.WithMessagef(err, "unable to add detected shared network %s to the database", + err = pkgerrors.WithMessagef(err, "unable to add detected shared network %s to the database", network.Name) return nil, err } @@ -581,10 +578,10 @@ func GetAppLocalSubnets(db *pg.DB, appID int64) ([]*LocalSubnet, error) { err := q.Select() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } - err = errors.Wrapf(err, "problem with getting all local subnets for app %d", appID) + err = pkgerrors.Wrapf(err, "problem with getting all local subnets for app %d", appID) return nil, err } return subnets, nil @@ -599,7 +596,7 @@ func (lsn *LocalSubnet) UpdateStats(db *pg.DB, stats map[string]interface{}) err q = q.WherePK() _, err := q.Update() if err != nil { - err = errors.Wrapf(err, "problem with updating stats in local subnet: [app:%d, subnet:%d, local subnet:%d]", + err = pkgerrors.Wrapf(err, "problem with updating stats in local subnet: [app:%d, subnet:%d, local subnet:%d]", lsn.AppID, lsn.SubnetID, lsn.LocalSubnetID) } return err @@ -614,7 +611,7 @@ func (s *Subnet) UpdateUtilization(db *pg.DB, addrUtilization, pdUtilization int q = q.WherePK() _, err := q.Update() if err != nil { - err = errors.Wrapf(err, "problem with updating utilization in the subnet: %d", + err = pkgerrors.Wrapf(err, "problem with updating utilization in the subnet: %d", s.ID) } return err diff --git a/backend/server/database/model/subnet_test.go b/backend/server/database/model/subnet_test.go index fef804f1b86db2058ef1b4d332f18a2003398265..2f0bef98247c7a155ed23dab2fba2084bd82736c 100644 --- a/backend/server/database/model/subnet_test.go +++ b/backend/server/database/model/subnet_test.go @@ -7,7 +7,6 @@ import ( "time" "github.com/stretchr/testify/require" - keaconfig "isc.org/stork/appcfg/kea" dbops "isc.org/stork/server/database" dbtest "isc.org/stork/server/database/test" @@ -700,7 +699,7 @@ func TestGetSubnetFamily(t *testing.T) { require.EqualValues(t, 6, s6.GetFamily()) } -// Check getting subnets with local subnets +// Check getting subnets with local subnets. func TestGetSubnetsWithLocalSubnets(t *testing.T) { db, _, teardown := dbtest.SetupDatabaseTestCase(t) defer teardown() @@ -731,7 +730,7 @@ func TestGetSubnetsWithLocalSubnets(t *testing.T) { require.EqualValues(t, 123, subnets[0].LocalSubnets[0].LocalSubnetID) } -// Check updating utilization in subnet +// Check updating utilization in subnet. func TestUpdateUtilization(t *testing.T) { db, _, teardown := dbtest.SetupDatabaseTestCase(t) defer teardown() diff --git a/backend/server/database/model/user.go b/backend/server/database/model/user.go index fdc46eb16044ea720d668c43e1516df4c8de92f0..2c5618e01df8f7961b7c83261e434b59c453e195 100644 --- a/backend/server/database/model/user.go +++ b/backend/server/database/model/user.go @@ -1,12 +1,12 @@ package dbmodel import ( + "errors" "fmt" "github.com/go-pg/pg/v9" "github.com/go-pg/pg/v9/orm" - "github.com/pkg/errors" - + pkgerrors "github.com/pkg/errors" dbops "isc.org/stork/server/database" ) @@ -75,7 +75,7 @@ func createUserGroups(db *pg.DB, user *SystemUser) (err error) { func CreateUser(db *pg.DB, user *SystemUser) (conflict bool, err error) { tx, err := db.Begin() if err != nil { - err = errors.Wrapf(err, "unable to begin transaction while trying to create user %s", user.Identity()) + err = pkgerrors.Wrapf(err, "unable to begin transaction while trying to create user %s", user.Identity()) return false, err } defer func() { @@ -90,12 +90,12 @@ func CreateUser(db *pg.DB, user *SystemUser) (conflict bool, err error) { } if err != nil { - pgErr, ok := err.(pg.Error) - if ok { - conflict = pgErr.IntegrityViolation() + var pgError pg.Error + if errors.As(err, &pgError) { + conflict = pgError.IntegrityViolation() } - err = errors.Wrapf(err, "database operation error while trying to create user %s", user.Identity()) + err = pkgerrors.Wrapf(err, "database operation error while trying to create user %s", user.Identity()) } if err == nil { @@ -111,7 +111,7 @@ func CreateUser(db *pg.DB, user *SystemUser) (conflict bool, err error) { func UpdateUser(db *pg.DB, user *SystemUser) (conflict bool, err error) { tx, err := db.Begin() if err != nil { - err = errors.Wrapf(err, "unable to begin transaction while trying to update user %s", user.Identity()) + err = pkgerrors.Wrapf(err, "unable to begin transaction while trying to update user %s", user.Identity()) return false, err } defer func() { @@ -131,16 +131,16 @@ func UpdateUser(db *pg.DB, user *SystemUser) (conflict bool, err error) { } if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { conflict = true } else { - pgErr, ok := err.(pg.Error) - if ok { - conflict = pgErr.IntegrityViolation() + var pgError pg.Error + if errors.As(err, &pgError) { + conflict = pgError.IntegrityViolation() } } - err = errors.Wrapf(err, "database operation error while trying to update user %s", user.Identity()) + err = pkgerrors.Wrapf(err, "database operation error while trying to update user %s", user.Identity()) } if err == nil { @@ -159,10 +159,10 @@ func SetPassword(db *pg.DB, id int, password string) (err error) { result, err := db.Model(&user).Column("password_hash").WherePK().Update() if err != nil { - err = errors.Wrapf(err, "database operation error while trying to set new password for the user id %d", + err = pkgerrors.Wrapf(err, "database operation error while trying to set new password for the user id %d", id) } else if result.RowsAffected() == 0 { - err = errors.Errorf("failed to update password for non existing user with id %d", id) + err = pkgerrors.Errorf("failed to update password for non existing user with id %d", id) } return err @@ -177,9 +177,8 @@ func ChangePassword(db *pg.DB, id int, oldPassword, newPassword string) (bool, e ok, err := db.Model(&user). Where("password_hash = crypt(?, password_hash) AND (id = ?)", oldPassword, id).Exists() - if err != nil { - err = errors.Wrapf(err, "database operation error while trying to change password of user with id %d", id) + err = pkgerrors.Wrapf(err, "database operation error while trying to change password of user with id %d", id) return false, err } @@ -198,15 +197,14 @@ func Authenticate(db *pg.DB, user *SystemUser) (bool, error) { err := db.Model(user).Relation("Groups"). Where("password_hash = crypt(?, password_hash) AND (login = ? OR email = ?)", user.Password, user.Login, user.Email).First() - if err != nil { // Failing to find an entry is not really an error. It merely means that the // authentication failed, so return false in this case. - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return false, nil } // Other types of errors have to be logged properly. - err = errors.Wrapf(err, "database operation error while trying to authenticate user %s", user.Identity()) + err = pkgerrors.Wrapf(err, "database operation error while trying to authenticate user %s", user.Identity()) return false, err } @@ -229,7 +227,7 @@ func Authenticate(db *pg.DB, user *SystemUser) (bool, error) { // used for sorting. in SortDirAny is used then ASC order is used. func GetUsersByPage(db *dbops.PgDB, offset, limit int64, filterText *string, sortField string, sortDir SortDirEnum) ([]SystemUser, int64, error) { if limit == 0 { - return nil, 0, errors.New("limit should be greater than 0") + return nil, 0, pkgerrors.New("limit should be greater than 0") } var users []SystemUser @@ -254,10 +252,10 @@ func GetUsersByPage(db *dbops.PgDB, offset, limit int64, filterText *string, sor total, err := q.SelectAndCount() if err != nil { - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return []SystemUser{}, 0, nil } - err = errors.Wrapf(err, "problem with fetching a list of users from the database") + err = pkgerrors.Wrapf(err, "problem with fetching a list of users from the database") } return users, int64(total), err @@ -269,10 +267,10 @@ func GetUsersByPage(db *dbops.PgDB, offset, limit int64, filterText *string, sor func GetUserByID(db *dbops.PgDB, id int) (*SystemUser, error) { user := &SystemUser{} err := db.Model(user).Relation("Groups").Where("id = ?", id).First() - if err == pg.ErrNoRows { + if errors.Is(err, pg.ErrNoRows) { return nil, nil } else if err != nil { - return nil, errors.Wrapf(err, "problem with fetching user %v from the database", id) + return nil, pkgerrors.Wrapf(err, "problem with fetching user %v from the database", id) } return user, err } @@ -287,7 +285,7 @@ func (user *SystemUser) AddToGroupByID(db *dbops.PgDB, group *SystemGroup) (adde return res.RowsAffected() > 0, err } - err = errors.Errorf("unable to add user to the unknown group") + err = pkgerrors.Errorf("unable to add user to the unknown group") return false, err } diff --git a/backend/server/database/model/user_test.go b/backend/server/database/model/user_test.go index abbb3dfa7a2f894d7f479a042a536104afd5e189..ec2f77861f5dbbb8b233049b73c1836ce5228f8e 100644 --- a/backend/server/database/model/user_test.go +++ b/backend/server/database/model/user_test.go @@ -6,7 +6,6 @@ import ( faker "github.com/brianvoe/gofakeit" "github.com/stretchr/testify/require" - dbops "isc.org/stork/server/database" dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/database/session/session_manager.go b/backend/server/database/session/session_manager.go index 82ccddadb86640b76fc1278d3eb48caf23ed37ec..6232df1e2daaec1d1c5c7e2dcca57ce58b3d57e6 100644 --- a/backend/server/database/session/session_manager.go +++ b/backend/server/database/session/session_manager.go @@ -9,9 +9,10 @@ import ( "github.com/alexedwards/scs/postgresstore" "github.com/alexedwards/scs/v2" - _ "github.com/lib/pq" // TODO: document why it is blank imported - "github.com/pkg/errors" + // TODO: document why it is blank imported. + _ "github.com/lib/pq" + "github.com/pkg/errors" dbops "isc.org/stork/server/database" dbmodel "isc.org/stork/server/database/model" ) diff --git a/backend/server/database/session/session_manager_test.go b/backend/server/database/session/session_manager_test.go index 1f171ffa563c737063f9f6384dd809abd611d30e..f9ec3381c684c3aaf394fd2525b4eba1195d5f39 100644 --- a/backend/server/database/session/session_manager_test.go +++ b/backend/server/database/session/session_manager_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/stretchr/testify/require" - dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/database/settings.go b/backend/server/database/settings.go index 838d320cad7710976f07b23ee3a5ae8bb295e9d7..2f8bf44ed2b9a75dca8651baf117473115dc86e0 100644 --- a/backend/server/database/settings.go +++ b/backend/server/database/settings.go @@ -13,7 +13,7 @@ import ( ) type BaseDatabaseSettings struct { - DbName string `short:"d" long:"db-name" description:"the name of the database to connect to" env:"STORK_DATABASE_NAME" default:"stork"` + DBName string `short:"d" long:"db-name" description:"the name of the database to connect to" env:"STORK_DATABASE_NAME" default:"stork"` User string `short:"u" long:"db-user" description:"the user name to be used for database connections" env:"STORK_DATABASE_USER_NAME" default:"stork"` Password string `description:"the database password to be used for database connections" env:"STORK_DATABASE_PASSWORD"` Host string `long:"db-host" description:"the name of the host where database is available" env:"STORK_DATABASE_HOST" default:"localhost"` @@ -25,10 +25,10 @@ type DatabaseSettings struct { TraceSQL string `long:"db-trace-queries" description:"enable tracing SQL queries: run (only runtime, without migrations), all (migrations and run-time), all is the default and covers both migrations and run-time." env:"STORK_DATABASE_TRACE" optional:"true" optional-value:"all"` } -// Alias to pg.DB +// Alias to pg.DB. type PgDB = pg.DB -// Alias to pg.Conn +// Alias to pg.Conn. type PgConn = pg.Conn // Alias to pg.Options. @@ -74,8 +74,8 @@ func (c *BaseDatabaseSettings) ConnectionParams() string { continue } // Escape quotes and double quotes. - fieldValue = strings.Replace(fieldValue, "'", `\'`, -1) - fieldValue = strings.Replace(fieldValue, `"`, `\"`, -1) + fieldValue = strings.ReplaceAll(fieldValue, "'", `\'`) + fieldValue = strings.ReplaceAll(fieldValue, `"`, `\"`) // Enclose all strings in quotes in case they contain spaces. fieldValue = fmt.Sprintf("'%s'", fieldValue) v.Field(i).SetString(fieldValue) @@ -85,6 +85,7 @@ func (c *BaseDatabaseSettings) ConnectionParams() string { if fieldValue == 0 { continue } + default: } // If we are not on the first field, add a space after previous field. if i > 0 { @@ -99,7 +100,7 @@ func (c *BaseDatabaseSettings) ConnectionParams() string { // Converts generic connection parameters to go-pg specific parameters. func (c *DatabaseSettings) PgParams() *PgOptions { - pgopts := &PgOptions{Database: c.DbName, User: c.User, Password: c.Password} + pgopts := &PgOptions{Database: c.DBName, User: c.User, Password: c.Password} pgopts.Addr = fmt.Sprintf("%s:%d", c.Host, c.Port) return pgopts } diff --git a/backend/server/database/test/connection_test.go b/backend/server/database/test/connection_test.go index 391b511a5ffaa4d4861b848865ce3802cd3358e0..9af5703f215fc674555d05eecd3c9f5441199409 100644 --- a/backend/server/database/test/connection_test.go +++ b/backend/server/database/test/connection_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - dbops "isc.org/stork/server/database" ) diff --git a/backend/server/database/test/dbtest.go b/backend/server/database/test/dbtest.go index 4a4a88f7798a3c7a3f61e2de913feb666dc54eea..a5a03e7ad8fe500fada8b9d4874edc701603cf78 100644 --- a/backend/server/database/test/dbtest.go +++ b/backend/server/database/test/dbtest.go @@ -11,7 +11,6 @@ import ( "time" "github.com/stretchr/testify/require" - dbops "isc.org/stork/server/database" ) @@ -24,7 +23,7 @@ func SetupDatabaseTestCase(testArg interface{}) (*dbops.PgDB, *dbops.DatabaseSet // of space separated options used by SQL drivers. genericConnOptions := dbops.DatabaseSettings{ BaseDatabaseSettings: dbops.BaseDatabaseSettings{ - DbName: "storktest", + DBName: "storktest", User: "storktest", Password: "storktest", Host: "localhost", @@ -66,7 +65,7 @@ func SetupDatabaseTestCase(testArg interface{}) (*dbops.PgDB, *dbops.DatabaseSet // Connect to base `postgres` database to be able to create test database. pgConnOptions.Database = "postgres" - db, err := dbops.NewPgDbConn(&pgConnOptions, false) + db, err := dbops.NewPgDBConn(&pgConnOptions, false) if db == nil { log.Fatalf("unable to create database instance: %+v", err) } @@ -79,6 +78,7 @@ func SetupDatabaseTestCase(testArg interface{}) (*dbops.PgDB, *dbops.DatabaseSet // Create test database from template. Template db is storktest (no tests should use it directly). // Test database name is storktest + big random number e.g.: storktest9817239871871478571. rand.Seed(time.Now().UnixNano()) + //nolint:gosec dbName := fmt.Sprintf("storktest%d", rand.Int63()) cmd := fmt.Sprintf(`DROP DATABASE IF EXISTS %s;`, dbName) @@ -101,9 +101,9 @@ func SetupDatabaseTestCase(testArg interface{}) (*dbops.PgDB, *dbops.DatabaseSet // Create an instance of the test database. pgConnOptions.Database = dbName - genericConnOptions.BaseDatabaseSettings.DbName = dbName + genericConnOptions.BaseDatabaseSettings.DBName = dbName - db, err = dbops.NewPgDbConn(&pgConnOptions, false) + db, err = dbops.NewPgDBConn(&pgConnOptions, false) if db == nil { log.Fatalf("unable to create database instance: %+v", err) } @@ -115,7 +115,7 @@ func SetupDatabaseTestCase(testArg interface{}) (*dbops.PgDB, *dbops.DatabaseSet // enable tracing sql queries if requested if _, ok := os.LookupEnv("STORK_DATABASE_TRACE"); ok { - db.AddQueryHook(dbops.DbLogger{}) + db.AddQueryHook(dbops.DBLogger{}) } return db, &genericConnOptions, func() { diff --git a/backend/server/database/test/migrations_test.go b/backend/server/database/test/migrations_test.go index 4ee9e608641e32632de89468dda58421dc551e4f..31b64c371c14c142a85c0f23ee3b90203d9817cd 100644 --- a/backend/server/database/test/migrations_test.go +++ b/backend/server/database/test/migrations_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - dbops "isc.org/stork/server/database" ) diff --git a/backend/server/database/test/settings_test.go b/backend/server/database/test/settings_test.go index 817f0e79b2192bccfc145fdfe802b5687c55dccb..7a99024e9f5ec7652e5269f73d1aa84b2fb2b13a 100644 --- a/backend/server/database/test/settings_test.go +++ b/backend/server/database/test/settings_test.go @@ -4,7 +4,6 @@ import ( "testing" "github.com/stretchr/testify/require" - dbops "isc.org/stork/server/database" ) @@ -13,7 +12,7 @@ import ( // with upper case letters is handled correctly. func TestConnectionParamsNoSpaces(t *testing.T) { settings := dbops.BaseDatabaseSettings{ - DbName: "stork", + DBName: "stork", User: "admin", Password: "StOrK123", Host: "localhost", @@ -27,7 +26,7 @@ func TestConnectionParamsNoSpaces(t *testing.T) { // Test that the password including space character is enclosed in quotes. func TestConnectionParamsWithSpaces(t *testing.T) { settings := dbops.BaseDatabaseSettings{ - DbName: "stork", + DBName: "stork", User: "admin", Password: "StOrK123 567", Host: "localhost", @@ -41,7 +40,7 @@ func TestConnectionParamsWithSpaces(t *testing.T) { // Test that quotes and double quotes are escaped. func TestConnectionParamsWithEscapes(t *testing.T) { settings := dbops.BaseDatabaseSettings{ - DbName: "stork", + DBName: "stork", User: "admin", Password: `StOrK123'56"7`, Host: "localhost", @@ -56,7 +55,7 @@ func TestConnectionParamsWithEscapes(t *testing.T) { // string. func TestConnectionParamsWithOptionalHost(t *testing.T) { settings := dbops.BaseDatabaseSettings{ - DbName: "stork", + DBName: "stork", User: "admin", Password: "StOrK123 567", Port: 123, @@ -69,7 +68,7 @@ func TestConnectionParamsWithOptionalHost(t *testing.T) { // Test that when the port is 0, it is not included in the connection string. func TestConnectionParamsWithOptionalPort(t *testing.T) { settings := dbops.BaseDatabaseSettings{ - DbName: "stork", + DBName: "stork", User: "admin", Password: "stork", Host: "localhost", diff --git a/backend/server/eventcenter/eventcenter.go b/backend/server/eventcenter/eventcenter.go index c0fbf4492fbe246b9ff7d7e4c6ab93a55d409ca8..ab13eb1d4973d7655b011ec9e178178003b6cad6 100644 --- a/backend/server/eventcenter/eventcenter.go +++ b/backend/server/eventcenter/eventcenter.go @@ -8,12 +8,11 @@ import ( "github.com/go-pg/pg/v9" log "github.com/sirupsen/logrus" - dbops "isc.org/stork/server/database" dbmodel "isc.org/stork/server/database/model" ) -// An interface to EventCenter +// An interface to EventCenter. type EventCenter interface { AddInfoEvent(text string, objects ...interface{}) AddWarningEvent(text string, objects ...interface{}) @@ -75,19 +74,19 @@ func CreateEvent(level int, text string, objects ...interface{}) *dbmodel.Event var details string for _, obj := range objects { if d, ok := obj.(*dbmodel.Daemon); ok { - text = strings.Replace(text, "{daemon}", daemonTag(d), -1) + text = strings.ReplaceAll(text, "{daemon}", daemonTag(d)) relations.DaemonID = d.ID } else if app, ok := obj.(*dbmodel.App); ok { - text = strings.Replace(text, "{app}", appTag(app), -1) + text = strings.ReplaceAll(text, "{app}", appTag(app)) relations.AppID = app.ID } else if m, ok := obj.(*dbmodel.Machine); ok { - text = strings.Replace(text, "{machine}", machineTag(m), -1) + text = strings.ReplaceAll(text, "{machine}", machineTag(m)) relations.MachineID = m.ID } else if s, ok := obj.(*dbmodel.Subnet); ok { - text = strings.Replace(text, "{subnet}", subnetTag(s), -1) + text = strings.ReplaceAll(text, "{subnet}", subnetTag(s)) relations.SubnetID = s.ID } else if u, ok := obj.(*dbmodel.SystemUser); ok { - text = strings.Replace(text, "{user}", userTag(u), -1) + text = strings.ReplaceAll(text, "{user}", userTag(u)) relations.UserID = int64(u.ID) } else if s, ok := obj.(string); ok { if len(s) > 0 { diff --git a/backend/server/eventcenter/eventcenter_test.go b/backend/server/eventcenter/eventcenter_test.go index 8c6bb7a36d78d353b3cc79166972659cbf150b70..8e853cc24931609429054d61e2c2ce6729a50245 100644 --- a/backend/server/eventcenter/eventcenter_test.go +++ b/backend/server/eventcenter/eventcenter_test.go @@ -5,7 +5,6 @@ import ( "time" "github.com/stretchr/testify/require" - dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/eventcenter/sse.go b/backend/server/eventcenter/sse.go index a0a9cc8d3e122b553bbfb0e676d49521d30481d3..fba9ef592ab9e69759400af18e884984bc665698 100644 --- a/backend/server/eventcenter/sse.go +++ b/backend/server/eventcenter/sse.go @@ -7,7 +7,6 @@ import ( "sync" log "github.com/sirupsen/logrus" - dbmodel "isc.org/stork/server/database/model" ) diff --git a/backend/server/eventcenter/sse_test.go b/backend/server/eventcenter/sse_test.go index 419fe5fd6447b80f8bb8e0b14d664be174518005..88854a8075e275c19076b3bf695e0659ba00d1ab 100644 --- a/backend/server/eventcenter/sse_test.go +++ b/backend/server/eventcenter/sse_test.go @@ -8,7 +8,6 @@ import ( "time" "github.com/stretchr/testify/require" - dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" ) diff --git a/backend/server/restservice/events.go b/backend/server/restservice/events.go index 51afc8b1d1e24bd131ff60276986b114a6a344ad..06f3945b16c1093c346bc9965b34ecb45f9fe5ee 100644 --- a/backend/server/restservice/events.go +++ b/backend/server/restservice/events.go @@ -7,7 +7,6 @@ import ( "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/strfmt" log "github.com/sirupsen/logrus" - dbmodel "isc.org/stork/server/database/model" "isc.org/stork/server/gen/models" "isc.org/stork/server/gen/restapi/operations/events" @@ -15,7 +14,7 @@ import ( func (r *RestAPI) getEvents(offset, limit int64, level int64, daemonType *string, appType *string, machineID *int64, userID *int64, sortField string, sortDir dbmodel.SortDirEnum) (*models.Events, error) { // Get the events from the database. - dbEvents, total, err := dbmodel.GetEventsByPage(r.Db, offset, limit, level, daemonType, appType, machineID, userID, sortField, sortDir) + dbEvents, total, err := dbmodel.GetEventsByPage(r.DB, offset, limit, level, daemonType, appType, machineID, userID, sortField, sortDir) if err != nil { return nil, err } diff --git a/backend/server/restservice/events_test.go b/backend/server/restservice/events_test.go index d26cebf5a6819aee1bc32ef5e1afbdd0826f26eb..fe8a631e3ae1a348125590e18317397b49881cdf 100644 --- a/backend/server/restservice/events_test.go +++ b/backend/server/restservice/events_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/stretchr/testify/require" - agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" diff --git a/backend/server/restservice/hosts.go b/backend/server/restservice/hosts.go index f06c740ce7ead3c111cdf81edefe7d630f6212b6..1f0c650c37dcc2b0fc246fb42ef1081a6a76afc6 100644 --- a/backend/server/restservice/hosts.go +++ b/backend/server/restservice/hosts.go @@ -6,7 +6,6 @@ import ( "github.com/go-openapi/runtime/middleware" log "github.com/sirupsen/logrus" - dbmodel "isc.org/stork/server/database/model" "isc.org/stork/server/gen/models" dhcp "isc.org/stork/server/gen/restapi/operations/d_h_c_p" @@ -15,7 +14,7 @@ import ( func (r *RestAPI) getHosts(offset, limit, appID int64, subnetID *int64, filterText *string, global *bool, sortField string, sortDir dbmodel.SortDirEnum) (*models.Hosts, error) { // Get the hosts from the database. - dbHosts, total, err := dbmodel.GetHostsByPage(r.Db, offset, limit, appID, subnetID, filterText, global, sortField, sortDir) + dbHosts, total, err := dbmodel.GetHostsByPage(r.DB, offset, limit, appID, subnetID, filterText, global, sortField, sortDir) if err != nil { return nil, err } diff --git a/backend/server/restservice/hosts_test.go b/backend/server/restservice/hosts_test.go index 7b894c9fc89545ecb3298fb5cbe85ddf15cdd824..69da9ce2972acacfe8f58086ff778b8a2634ea19 100644 --- a/backend/server/restservice/hosts_test.go +++ b/backend/server/restservice/hosts_test.go @@ -6,7 +6,6 @@ import ( "github.com/go-pg/pg/v9" "github.com/stretchr/testify/require" - agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" diff --git a/backend/server/restservice/logs.go b/backend/server/restservice/logs.go index 988bed5689d7a87d89c2540d75b2700dc5c78554..386e83ff1d2df3ea5cdf5e17ab9586334a737ba2 100644 --- a/backend/server/restservice/logs.go +++ b/backend/server/restservice/logs.go @@ -8,7 +8,6 @@ import ( "github.com/go-openapi/runtime/middleware" log "github.com/sirupsen/logrus" - dbmodel "isc.org/stork/server/database/model" "isc.org/stork/server/gen/models" "isc.org/stork/server/gen/restapi/operations/services" @@ -18,7 +17,7 @@ import ( func (r *RestAPI) GetLogTail(ctx context.Context, params services.GetLogTailParams) middleware.Responder { // We have ID of the log file to display. We need to get the details // of the file from the database. - dbLogTarget, err := dbmodel.GetLogTargetByID(r.Db, params.ID) + dbLogTarget, err := dbmodel.GetLogTargetByID(r.DB, params.ID) if err != nil { msg := fmt.Sprintf("cannot get information about the log file with id %d from the database", params.ID) log.Error(msg) diff --git a/backend/server/restservice/logs_test.go b/backend/server/restservice/logs_test.go index f5742284c66f69cbdab3c5e71552d131ef2fc626..150e2b4739a1ac43390187299203f44cf5c86cb6 100644 --- a/backend/server/restservice/logs_test.go +++ b/backend/server/restservice/logs_test.go @@ -7,7 +7,6 @@ import ( "testing" "github.com/stretchr/testify/require" - agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" diff --git a/backend/server/restservice/machines.go b/backend/server/restservice/machines.go index 2914a1b67efe4028f3fbcd94208e5dfcc713746e..f0291cc982cd4aa76a7f2280e70e4558d3d5c5c5 100644 --- a/backend/server/restservice/machines.go +++ b/backend/server/restservice/machines.go @@ -12,11 +12,11 @@ import ( "github.com/go-openapi/strfmt" "github.com/pkg/errors" log "github.com/sirupsen/logrus" - "isc.org/stork" "isc.org/stork/server/agentcomm" "isc.org/stork/server/apps" "isc.org/stork/server/apps/kea" + dbops "isc.org/stork/server/database" dbmodel "isc.org/stork/server/database/model" "isc.org/stork/server/gen/models" dhcp "isc.org/stork/server/gen/restapi/operations/d_h_c_p" @@ -72,7 +72,7 @@ func (r *RestAPI) machineToRestAPI(dbMachine dbmodel.Machine) *models.Machine { // Get runtime state of indicated machine. func (r *RestAPI) GetMachineState(ctx context.Context, params services.GetMachineStateParams) middleware.Responder { - dbMachine, err := dbmodel.GetMachineByID(r.Db, params.ID) + dbMachine, err := dbmodel.GetMachineByID(r.DB, params.ID) if err != nil { msg := fmt.Sprintf("cannot get machine with id %d from db", params.ID) log.Error(err) @@ -89,7 +89,7 @@ func (r *RestAPI) GetMachineState(ctx context.Context, params services.GetMachin return rsp } - errStr := apps.GetMachineAndAppsState(ctx, r.Db, dbMachine, r.Agents, r.EventCenter) + errStr := apps.GetMachineAndAppsState(ctx, r.DB, dbMachine, r.Agents, r.EventCenter) if errStr != "" { rsp := services.NewGetMachineStateDefault(http.StatusInternalServerError).WithPayload(&models.APIError{ Message: &errStr, @@ -104,7 +104,7 @@ func (r *RestAPI) GetMachineState(ctx context.Context, params services.GetMachin } func (r *RestAPI) getMachines(offset, limit int64, filterText *string, sortField string, sortDir dbmodel.SortDirEnum) (*models.Machines, error) { - dbMachines, total, err := dbmodel.GetMachinesByPage(r.Db, offset, limit, filterText, sortField, sortDir) + dbMachines, total, err := dbmodel.GetMachinesByPage(r.DB, offset, limit, filterText, sortField, sortDir) if err != nil { return nil, err } @@ -164,7 +164,7 @@ func (r *RestAPI) GetMachines(ctx context.Context, params services.GetMachinesPa // Get one machine by ID where Stork Agent is running. func (r *RestAPI) GetMachine(ctx context.Context, params services.GetMachineParams) middleware.Responder { - dbMachine, err := dbmodel.GetMachineByID(r.Db, params.ID) + dbMachine, err := dbmodel.GetMachineByID(r.DB, params.ID) if err != nil { msg := fmt.Sprintf("cannot get machine with id %d from db", params.ID) log.Error(err) @@ -213,7 +213,7 @@ func (r *RestAPI) CreateMachine(ctx context.Context, params services.CreateMachi return rsp } - dbMachine, err := dbmodel.GetMachineByAddressAndAgentPort(r.Db, addr, params.Machine.AgentPort) + dbMachine, err := dbmodel.GetMachineByAddressAndAgentPort(r.DB, addr, params.Machine.AgentPort) if err == nil && dbMachine != nil { msg := fmt.Sprintf("machine %s:%d already exists", addr, params.Machine.AgentPort) log.Warnf(msg) @@ -225,7 +225,7 @@ func (r *RestAPI) CreateMachine(ctx context.Context, params services.CreateMachi if dbMachine == nil { dbMachine = &dbmodel.Machine{Address: addr, AgentPort: params.Machine.AgentPort} - err = dbmodel.AddMachine(r.Db, dbMachine) + err = dbmodel.AddMachine(r.DB, dbMachine) if err != nil { msg := fmt.Sprintf("cannot store machine %s", addr) log.Error(err) @@ -237,7 +237,7 @@ func (r *RestAPI) CreateMachine(ctx context.Context, params services.CreateMachi r.EventCenter.AddInfoEvent("added {machine}", dbMachine) } - errStr := apps.GetMachineAndAppsState(ctx, r.Db, dbMachine, r.Agents, r.EventCenter) + errStr := apps.GetMachineAndAppsState(ctx, r.DB, dbMachine, r.Agents, r.EventCenter) if errStr != "" { rsp := services.NewCreateMachineDefault(http.StatusInternalServerError).WithPayload(&models.APIError{ Message: &errStr, @@ -279,7 +279,7 @@ func (r *RestAPI) UpdateMachine(ctx context.Context, params services.UpdateMachi return rsp } - dbMachine, err := dbmodel.GetMachineByID(r.Db, params.ID) + dbMachine, err := dbmodel.GetMachineByID(r.DB, params.ID) if err != nil { msg := fmt.Sprintf("cannot get machine with id %d from db", params.ID) log.Error(err) @@ -298,7 +298,7 @@ func (r *RestAPI) UpdateMachine(ctx context.Context, params services.UpdateMachi // check if there is no duplicate if dbMachine.Address != addr || dbMachine.AgentPort != params.Machine.AgentPort { - dbMachine2, err := dbmodel.GetMachineByAddressAndAgentPort(r.Db, addr, params.Machine.AgentPort) + dbMachine2, err := dbmodel.GetMachineByAddressAndAgentPort(r.DB, addr, params.Machine.AgentPort) if err == nil && dbMachine2 != nil && dbMachine2.ID != dbMachine.ID { msg := fmt.Sprintf("machine with address %s:%d already exists", *params.Machine.Address, params.Machine.AgentPort) @@ -312,7 +312,7 @@ func (r *RestAPI) UpdateMachine(ctx context.Context, params services.UpdateMachi // copy fields dbMachine.Address = addr dbMachine.AgentPort = params.Machine.AgentPort - err = r.Db.Update(dbMachine) + err = r.DB.Update(dbMachine) if err != nil { msg := fmt.Sprintf("cannot update machine with id %d in db", params.ID) log.Error(err) @@ -328,7 +328,7 @@ func (r *RestAPI) UpdateMachine(ctx context.Context, params services.UpdateMachi // Add a machine where Stork Agent is running. func (r *RestAPI) DeleteMachine(ctx context.Context, params services.DeleteMachineParams) middleware.Responder { - dbMachine, err := dbmodel.GetMachineByID(r.Db, params.ID) + dbMachine, err := dbmodel.GetMachineByID(r.DB, params.ID) if err == nil && dbMachine == nil { rsp := services.NewDeleteMachineOK() return rsp @@ -341,7 +341,7 @@ func (r *RestAPI) DeleteMachine(ctx context.Context, params services.DeleteMachi return rsp } - err = dbmodel.DeleteMachine(r.Db, dbMachine) + err = dbmodel.DeleteMachine(r.DB, dbMachine) if err != nil { msg := fmt.Sprintf("cannot delete machine %d", params.ID) log.Error(err) @@ -514,7 +514,7 @@ func (r *RestAPI) appToRestAPI(dbApp *dbmodel.App) *models.App { } func (r *RestAPI) getApps(offset, limit int64, filterText *string, appType string, sortField string, sortDir dbmodel.SortDirEnum) (*models.Apps, error) { - dbApps, total, err := dbmodel.GetAppsByPage(r.Db, offset, limit, filterText, appType, sortField, sortDir) + dbApps, total, err := dbmodel.GetAppsByPage(r.DB, offset, limit, filterText, appType, sortField, sortDir) if err != nil { return nil, err } @@ -566,7 +566,7 @@ func (r *RestAPI) GetApps(ctx context.Context, params services.GetAppsParams) mi } func (r *RestAPI) GetApp(ctx context.Context, params services.GetAppParams) middleware.Responder { - dbApp, err := dbmodel.GetAppByID(r.Db, params.ID) + dbApp, err := dbmodel.GetAppByID(r.DB, params.ID) if err != nil { msg := fmt.Sprintf("cannot get app with id %d from db", params.ID) log.Error(err) @@ -593,9 +593,141 @@ func (r *RestAPI) GetApp(ctx context.Context, params services.GetAppParams) midd return rsp } +// Gets current status of services for a given Kea application. +func getKeaServicesStatus(db *dbops.PgDB, app *dbmodel.App) *models.ServicesStatus { + servicesStatus := &models.ServicesStatus{} + + keaServices, err := dbmodel.GetDetailedServicesByAppID(db, app.ID) + if err != nil { + log.Error(err) + + return nil + } + + for _, s := range keaServices { + if s.HAService == nil { + continue + } + ha := s.HAService + keaStatus := models.KeaStatus{ + Daemon: ha.HAType, + } + secondaryRole := "secondary" + if ha.HAMode == "hot-standby" { + secondaryRole = "standby" + } + // Calculate age. + age := make([]int64, 2) + statusTime := make([]strfmt.DateTime, 2) + now := storkutil.UTCNow() + for i, t := range []time.Time{ha.PrimaryStatusCollectedAt, ha.SecondaryStatusCollectedAt} { + // If status time hasn't been set yet, return a negative age value to + // indicate that it cannot be displayed. + if t.IsZero() || now.Before(t) { + age[i] = -1 + } else { + age[i] = int64(now.Sub(t).Seconds()) + statusTime[i] = strfmt.DateTime(t) + } + } + // Format failover times into string. + failoverTime := make([]strfmt.DateTime, 2) + for i, t := range []time.Time{ha.PrimaryLastFailoverAt, ha.SecondaryLastFailoverAt} { + // Only display the non-zero failover times and the times that are + // before current time. + if !t.IsZero() && now.After(t) { + failoverTime[i] = strfmt.DateTime(t) + } + } + // Get the control addresses and app ids for daemons taking part in HA. + controlAddress := make([]string, 2) + appID := make([]int64, 2) + for i := range s.Daemons { + if s.Daemons[i].ID == ha.PrimaryID { + ap, _ := s.Daemons[i].App.GetAccessPoint("control") + if ap != nil { + controlAddress[0] = ap.Address + } + appID[0] = s.Daemons[i].App.ID + } else if s.Daemons[i].ID == ha.SecondaryID { + ap, _ := s.Daemons[i].App.GetAccessPoint("control") + if ap != nil { + controlAddress[1] = ap.Address + } + appID[1] = s.Daemons[i].App.ID + } + } + // Get the communication state value. + commInterrupted := make([]int64, 2) + for i, c := range []*bool{ha.PrimaryCommInterrupted, ha.SecondaryCommInterrupted} { + if c == nil { + // Negative value indicates that the communication state is unknown. + // Quite possibly that we're running earlier Kea version that doesn't + // provide this information. + commInterrupted[i] = -1 + } else if *c { + // Communication interrupted. + commInterrupted[i] = 1 + } + } + keaStatus.HaServers = &models.KeaStatusHaServers{ + PrimaryServer: &models.KeaHAServerStatus{ + Age: age[0], + AppID: appID[0], + ControlAddress: controlAddress[0], + FailoverTime: failoverTime[0], + ID: ha.PrimaryID, + InTouch: ha.PrimaryReachable, + Role: "primary", + Scopes: ha.PrimaryLastScopes, + State: ha.PrimaryLastState, + StatusTime: statusTime[0], + CommInterrupted: commInterrupted[0], + ConnectingClients: ha.PrimaryConnectingClients, + UnackedClients: ha.PrimaryUnackedClients, + UnackedClientsLeft: ha.PrimaryUnackedClientsLeft, + AnalyzedPackets: ha.PrimaryAnalyzedPackets, + }, + } + + // Including the information about the secondary server only + // makes sense for load-balancing and hot-standby mode. + if ha.HAMode != "passive-backup" { + keaStatus.HaServers.SecondaryServer = &models.KeaHAServerStatus{ + Age: age[1], + AppID: appID[1], + ControlAddress: controlAddress[1], + FailoverTime: failoverTime[1], + ID: ha.SecondaryID, + InTouch: ha.SecondaryReachable, + Role: secondaryRole, + Scopes: ha.SecondaryLastScopes, + State: ha.SecondaryLastState, + StatusTime: statusTime[1], + CommInterrupted: commInterrupted[1], + ConnectingClients: ha.SecondaryConnectingClients, + UnackedClients: ha.SecondaryUnackedClients, + UnackedClientsLeft: ha.SecondaryUnackedClientsLeft, + AnalyzedPackets: ha.SecondaryAnalyzedPackets, + } + } + + serviceStatus := &models.ServiceStatus{ + Status: struct { + models.KeaStatus + }{ + keaStatus, + }, + } + servicesStatus.Items = append(servicesStatus.Items, serviceStatus) + } + + return servicesStatus +} + // Gets current status of services which the given application is associated with. func (r *RestAPI) GetAppServicesStatus(ctx context.Context, params services.GetAppServicesStatusParams) middleware.Responder { - dbApp, err := dbmodel.GetAppByID(r.Db, params.ID) + dbApp, err := dbmodel.GetAppByID(r.DB, params.ID) if err != nil { log.Error(err) msg := fmt.Sprintf("cannot get app with id %d from the database", params.ID) @@ -614,138 +746,21 @@ func (r *RestAPI) GetAppServicesStatus(ctx context.Context, params services.GetA return rsp } - servicesStatus := &models.ServicesStatus{} + var servicesStatus *models.ServicesStatus // If this is Kea application, get the Kea DHCP servers status which possibly // includes HA status. if dbApp.Type == dbmodel.AppTypeKea { - keaServices, err := dbmodel.GetDetailedServicesByAppID(r.Db, dbApp.ID) - if err != nil { - log.Error(err) - msg := fmt.Sprintf("cannot get status of the app with id %d", params.ID) + servicesStatus = getKeaServicesStatus(r.DB, dbApp) + if servicesStatus == nil { + msg := fmt.Sprintf("cannot get status of the app with id %d", dbApp.ID) rsp := services.NewGetAppServicesStatusDefault(http.StatusInternalServerError).WithPayload(&models.APIError{ Message: &msg, }) return rsp } - - for _, s := range keaServices { - if s.HAService == nil { - continue - } - ha := s.HAService - keaStatus := models.KeaStatus{ - Daemon: ha.HAType, - } - secondaryRole := "secondary" - if ha.HAMode == "hot-standby" { - secondaryRole = "standby" - } - // Calculate age. - age := make([]int64, 2) - statusTime := make([]strfmt.DateTime, 2) - now := storkutil.UTCNow() - for i, t := range []time.Time{ha.PrimaryStatusCollectedAt, ha.SecondaryStatusCollectedAt} { - // If status time hasn't been set yet, return a negative age value to - // indicate that it cannot be displayed. - if t.IsZero() || now.Before(t) { - age[i] = -1 - } else { - age[i] = int64(now.Sub(t).Seconds()) - statusTime[i] = strfmt.DateTime(t) - } - } - // Format failover times into string. - failoverTime := make([]strfmt.DateTime, 2) - for i, t := range []time.Time{ha.PrimaryLastFailoverAt, ha.SecondaryLastFailoverAt} { - // Only display the non-zero failover times and the times that are - // before current time. - if !t.IsZero() && now.After(t) { - failoverTime[i] = strfmt.DateTime(t) - } - } - // Get the control addresses and app ids for daemons taking part in HA. - controlAddress := make([]string, 2) - appID := make([]int64, 2) - for i := range s.Daemons { - if s.Daemons[i].ID == ha.PrimaryID { - ap, _ := s.Daemons[i].App.GetAccessPoint("control") - if ap != nil { - controlAddress[0] = ap.Address - } - appID[0] = s.Daemons[i].App.ID - } else if s.Daemons[i].ID == ha.SecondaryID { - ap, _ := s.Daemons[i].App.GetAccessPoint("control") - if ap != nil { - controlAddress[1] = ap.Address - } - appID[1] = s.Daemons[i].App.ID - } - } - // Get the communication state value. - commInterrupted := make([]int64, 2) - for i, c := range []*bool{ha.PrimaryCommInterrupted, ha.SecondaryCommInterrupted} { - if c == nil { - // Negative value indicates that the communication state is unknown. - // Quite possibly that we're running earlier Kea version that doesn't - // provide this information. - commInterrupted[i] = -1 - } else if *c { - // Communication interrupted. - commInterrupted[i] = 1 - } - } - keaStatus.HaServers = &models.KeaStatusHaServers{ - PrimaryServer: &models.KeaHAServerStatus{ - Age: age[0], - AppID: appID[0], - ControlAddress: controlAddress[0], - FailoverTime: failoverTime[0], - ID: ha.PrimaryID, - InTouch: ha.PrimaryReachable, - Role: "primary", - Scopes: ha.PrimaryLastScopes, - State: ha.PrimaryLastState, - StatusTime: statusTime[0], - CommInterrupted: commInterrupted[0], - ConnectingClients: ha.PrimaryConnectingClients, - UnackedClients: ha.PrimaryUnackedClients, - UnackedClientsLeft: ha.PrimaryUnackedClientsLeft, - AnalyzedPackets: ha.PrimaryAnalyzedPackets, - }, - } - - // Including the information about the secondary server only - // makes sense for load-balancing and hot-standby mode. - if ha.HAMode != "passive-backup" { - keaStatus.HaServers.SecondaryServer = &models.KeaHAServerStatus{ - Age: age[1], - AppID: appID[1], - ControlAddress: controlAddress[1], - FailoverTime: failoverTime[1], - ID: ha.SecondaryID, - InTouch: ha.SecondaryReachable, - Role: secondaryRole, - Scopes: ha.SecondaryLastScopes, - State: ha.SecondaryLastState, - StatusTime: statusTime[1], - CommInterrupted: commInterrupted[1], - ConnectingClients: ha.SecondaryConnectingClients, - UnackedClients: ha.SecondaryUnackedClients, - UnackedClientsLeft: ha.SecondaryUnackedClientsLeft, - AnalyzedPackets: ha.SecondaryAnalyzedPackets, - } - } - - serviceStatus := &models.ServiceStatus{ - Status: struct { - models.KeaStatus - }{ - keaStatus, - }, - } - servicesStatus.Items = append(servicesStatus.Items, serviceStatus) - } + } else { + servicesStatus = &models.ServicesStatus{} } rsp := services.NewGetAppServicesStatusOK().WithPayload(servicesStatus) @@ -754,9 +769,9 @@ func (r *RestAPI) GetAppServicesStatus(ctx context.Context, params services.GetA // Get statistics about applications. func (r *RestAPI) GetAppsStats(ctx context.Context, params services.GetAppsStatsParams) middleware.Responder { - dbApps, err := dbmodel.GetAllApps(r.Db) + dbApps, err := dbmodel.GetAllApps(r.DB) if err != nil { - msg := fmt.Sprintf("cannot get all apps from db") + msg := "cannot get all apps from db" log.Error(err) rsp := services.NewGetAppsStatsDefault(http.StatusInternalServerError).WithPayload(&models.APIError{ Message: &msg, @@ -834,7 +849,7 @@ func (r *RestAPI) GetDhcpOverview(ctx context.Context, params dhcp.GetDhcpOvervi } // get dhcp statistics - stats, err := dbmodel.GetAllStats(r.Db) + stats, err := dbmodel.GetAllStats(r.DB) if err != nil { msg := "cannot get statistics from db" log.Error(err) @@ -858,7 +873,7 @@ func (r *RestAPI) GetDhcpOverview(ctx context.Context, params dhcp.GetDhcpOvervi } // get kea apps and daemons statuses - dbApps, err := dbmodel.GetAppsByType(r.Db, dbmodel.AppTypeKea) + dbApps, err := dbmodel.GetAppsByType(r.DB, dbmodel.AppTypeKea) if err != nil { msg := "cannot get statistics from db" log.Error(err) @@ -952,7 +967,7 @@ func (r *RestAPI) GetDhcpOverview(ctx context.Context, params dhcp.GetDhcpOvervi // Update a daemon. func (r *RestAPI) UpdateDaemon(ctx context.Context, params services.UpdateDaemonParams) middleware.Responder { - dbDaemon, err := dbmodel.GetDaemonByID(r.Db, params.ID) + dbDaemon, err := dbmodel.GetDaemonByID(r.DB, params.ID) if err != nil { msg := fmt.Sprintf("cannot get daemon with id %d from db", params.ID) log.Error(err) @@ -973,7 +988,7 @@ func (r *RestAPI) UpdateDaemon(ctx context.Context, params services.UpdateDaemon dbDaemon.Monitored = params.Daemon.Monitored - err = dbmodel.UpdateDaemon(r.Db, dbDaemon) + err = dbmodel.UpdateDaemon(r.DB, dbDaemon) if err != nil { msg := fmt.Sprintf("failed updating daemon with id %d", params.ID) rsp := services.NewUpdateDaemonDefault(http.StatusInternalServerError).WithPayload(&models.APIError{ diff --git a/backend/server/restservice/machines_test.go b/backend/server/restservice/machines_test.go index 2178f286a79a2a3e554e2140bc4ac7fba5103a89..1ccdf383cb42a1896b44b19aac8613a048a90e5c 100644 --- a/backend/server/restservice/machines_test.go +++ b/backend/server/restservice/machines_test.go @@ -7,7 +7,6 @@ import ( "time" "github.com/stretchr/testify/require" - keactrl "isc.org/stork/appctrl/kea" "isc.org/stork/server/agentcomm" agentcommtest "isc.org/stork/server/agentcomm/test" @@ -335,7 +334,7 @@ func TestGetMachines(t *testing.T) { rsp := rapi.GetMachines(ctx, params) ms := rsp.(*services.GetMachinesOK).Payload require.EqualValues(t, ms.Total, 0) - //require.Greater(t, ms.Items, ) + // require.Greater(t, ms.Items, ) } func TestGetMachine(t *testing.T) { @@ -1352,7 +1351,7 @@ func TestUpdateDaemon(t *testing.T) { require.True(t, okRsp.Payload.Details.AppKea.Daemons[0].Monitored) // now it is true // setup a user session (UpdateDaemon needs user db object) - user, err := dbmodel.GetUserByID(rapi.Db, 1) + user, err := dbmodel.GetUserByID(rapi.DB, 1) require.NoError(t, err) ctx2, err := rapi.SessionManager.Load(ctx, "") require.NoError(t, err) diff --git a/backend/server/restservice/middleware.go b/backend/server/restservice/middleware.go index 303abec9a56e1efb627daf57d52b6f4de5cd89fe..73d0c3c01cd6344bb3878a978ba297964b502363 100644 --- a/backend/server/restservice/middleware.go +++ b/backend/server/restservice/middleware.go @@ -1,15 +1,14 @@ package restservice import ( - "fmt" "net/http" "os" "path" "strings" "time" + "github.com/pkg/errors" log "github.com/sirupsen/logrus" - "isc.org/stork/server/auth" "isc.org/stork/server/eventcenter" ) @@ -35,8 +34,8 @@ func loggingMiddleware(next http.Handler) http.Handler { duration := time.Since(start) entry = entry.WithFields(log.Fields{ - //"status": w.Status(), - //"text_status": http.StatusText(w.Status()), + // "status": w.Status(), + // "text_status": http.StatusText(w.Status()), "took": duration, }) entry.Info("served request") @@ -87,7 +86,7 @@ func (r *RestAPI) GlobalMiddleware(handler http.Handler, staticFilesDir string, } // Inner middleware function provides a common place to setup middlewares for -// the server. It is invoked after routing but before authentication, binding and validation +// the server. It is invoked after routing but before authentication, binding and validation. func (r *RestAPI) InnerMiddleware(handler http.Handler) http.Handler { // last handler is executed first for incoming request handler = r.SessionManager.SessionMiddleware(handler) @@ -98,12 +97,12 @@ func (r *RestAPI) InnerMiddleware(handler http.Handler) http.Handler { func (r *RestAPI) Authorizer(req *http.Request) error { ok, u := r.SessionManager.Logged(req.Context()) if !ok { - return fmt.Errorf("user unauthorized") + return errors.Errorf("user unauthorized") } ok, _ = auth.Authorize(u, req) if !ok { - return fmt.Errorf("user logged in but not allowed to access the resource") + return errors.Errorf("user logged in but not allowed to access the resource") } return nil diff --git a/backend/server/restservice/middleware_test.go b/backend/server/restservice/middleware_test.go index 036be6dcc2aef39f175e768445f8fa2000e41596..3fd0f4b5b894f1ada1ef97336ce7ffa2d90bf001 100644 --- a/backend/server/restservice/middleware_test.go +++ b/backend/server/restservice/middleware_test.go @@ -6,7 +6,6 @@ import ( "testing" "github.com/stretchr/testify/require" - agentcommtest "isc.org/stork/server/agentcomm/test" dbsession "isc.org/stork/server/database/session" dbtest "isc.org/stork/server/database/test" @@ -54,7 +53,7 @@ func TestInnerMiddleware(t *testing.T) { fec := &storktest.FakeEventCenter{} rapi, err := NewRestAPI(&settings, dbSettings, db, fa, fec) require.NoError(t, err) - sm, err := dbsession.NewSessionMgr(&rapi.DbSettings.BaseDatabaseSettings) + sm, err := dbsession.NewSessionMgr(&rapi.DBSettings.BaseDatabaseSettings) require.NoError(t, err) rapi.SessionManager = sm diff --git a/backend/server/restservice/restservice.go b/backend/server/restservice/restservice.go index 0fe4f8ad458844cf7538ac1e6f54b3f5a19f2e58..25309caeb6a956060903784b9e6bd1b8085656af 100644 --- a/backend/server/restservice/restservice.go +++ b/backend/server/restservice/restservice.go @@ -4,6 +4,7 @@ import ( "context" "crypto/tls" "crypto/x509" + "errors" "io/ioutil" "net" "net/http" @@ -14,10 +15,9 @@ import ( "github.com/go-openapi/swag" "github.com/go-pg/pg/v9" flags "github.com/jessevdk/go-flags" - "github.com/pkg/errors" + pkgerrors "github.com/pkg/errors" log "github.com/sirupsen/logrus" "golang.org/x/net/netutil" - "isc.org/stork/server/agentcomm" dbops "isc.org/stork/server/database" dbsession "isc.org/stork/server/database/session" @@ -48,8 +48,8 @@ type RestAPISettings struct { // Runtime information and settings for ReST API service. type RestAPI struct { Settings *RestAPISettings - DbSettings *dbops.DatabaseSettings - Db *dbops.PgDB + DBSettings *dbops.DatabaseSettings + DB *dbops.PgDB SessionManager *dbsession.SessionMgr EventCenter eventcenter.EventCenter @@ -70,13 +70,13 @@ func NewRestAPI(settings *RestAPISettings, dbSettings *dbops.DatabaseSettings, d // Initialize sessions with access to the database. sm, err := dbsession.NewSessionMgr(&dbSettings.BaseDatabaseSettings) if err != nil { - return nil, errors.Wrap(err, "unable to establish connection to the session database") + return nil, pkgerrors.Wrap(err, "unable to establish connection to the session database") } r := &RestAPI{ Settings: settings, - DbSettings: dbSettings, - Db: db, + DBSettings: dbSettings, + DB: db, SessionManager: sm, Agents: agents, EventCenter: eventCenter, @@ -116,7 +116,7 @@ func prepareTLS(httpServer *http.Server, s *RestAPISettings) error { httpServer.TLSConfig.Certificates = make([]tls.Certificate, 1) httpServer.TLSConfig.Certificates[0], err = tls.LoadX509KeyPair(string(s.TLSCertificate), string(s.TLSCertificateKey)) if err != nil { - return errors.Wrap(err, "problem with setting up certificates") + return pkgerrors.Wrap(err, "problem with setting up certificates") } } @@ -124,12 +124,12 @@ func prepareTLS(httpServer *http.Server, s *RestAPISettings) error { // include specified CA certificate caCert, caCertErr := ioutil.ReadFile(string(s.TLSCACertificate)) if caCertErr != nil { - return errors.Wrap(caCertErr, "problem with setting up certificates") + return pkgerrors.Wrap(caCertErr, "problem with setting up certificates") } caCertPool := x509.NewCertPool() ok := caCertPool.AppendCertsFromPEM(caCert) if !ok { - return errors.New("cannot parse CA certificate") + return pkgerrors.New("cannot parse CA certificate") } httpServer.TLSConfig.ClientCAs = caCertPool httpServer.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert @@ -156,7 +156,7 @@ func prepareTLS(httpServer *http.Server, s *RestAPISettings) error { return nil } -// Serve the API +// Serve the API. func (r *RestAPI) Serve() (err error) { // Initiate the http handler, with the objects that are implementing the business logic. h, err := restapi.Handler(restapi.Config{ @@ -180,7 +180,7 @@ func (r *RestAPI) Serve() (err error) { }, }) if err != nil { - return errors.Wrap(err, "cannot setup ReST API handler") + return pkgerrors.Wrap(err, "cannot setup ReST API handler") } r.handler = h @@ -193,7 +193,7 @@ func (r *RestAPI) Serve() (err error) { // set default handler, if none is set if r.handler == nil { if r.api == nil { - return errors.New("can't create the default handler, as no API is set") + return pkgerrors.New("can't create the default handler, as no API is set") } r.handler = r.api.Serve(nil) @@ -239,15 +239,15 @@ func (r *RestAPI) Serve() (err error) { log.WithFields(log.Fields{ "address": scheme + lstnr.Addr().String(), }).Infof("started serving Stork Server") - if err := httpServer.Serve(lstnr); err != nil && err != http.ErrServerClosed { - return errors.Wrap(err, "problem with serving") + if err := httpServer.Serve(lstnr); err != nil && !errors.Is(err, http.ErrServerClosed) { + return pkgerrors.Wrap(err, "problem with serving") } log.Info("stopped serving Stork Server") return nil } -// Listen creates the listeners for the server +// Listen creates the listeners for the server. func (r *RestAPI) Listen() error { if r.hasListeners { // already done this return nil @@ -265,12 +265,12 @@ func (r *RestAPI) Listen() error { // TLS disabled listener, err := net.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port))) if err != nil { - return errors.Wrap(err, "problem occurred while starting to listen using ReST API") + return pkgerrors.Wrap(err, "problem occurred while starting to listen using ReST API") } h, p, err := swag.SplitHostPort(listener.Addr().String()) if err != nil { - return errors.Wrap(err, "problem with address") + return pkgerrors.Wrap(err, "problem with address") } r.Host = h r.Port = p @@ -280,12 +280,12 @@ func (r *RestAPI) Listen() error { tlsListener, err := net.Listen("tcp", net.JoinHostPort(s.Host, strconv.Itoa(s.Port))) if err != nil { - return errors.Wrap(err, "problem occurred while starting to listen using ReST API") + return pkgerrors.Wrap(err, "problem occurred while starting to listen using ReST API") } sh, sp, err := swag.SplitHostPort(tlsListener.Addr().String()) if err != nil { - return errors.Wrap(err, "problem with address") + return pkgerrors.Wrap(err, "problem with address") } r.Host = sh r.Port = sp diff --git a/backend/server/restservice/search.go b/backend/server/restservice/search.go index c2b3596dd37650534e0154679088ccb46bd3e29a..6763f5fcbd1f35fcc4b5e21d0c45867ec27c34e2 100644 --- a/backend/server/restservice/search.go +++ b/backend/server/restservice/search.go @@ -7,7 +7,6 @@ import ( "github.com/go-openapi/runtime/middleware" log "github.com/sirupsen/logrus" - dbmodel "isc.org/stork/server/database/model" "isc.org/stork/server/gen/models" "isc.org/stork/server/gen/restapi/operations/search" diff --git a/backend/server/restservice/search_test.go b/backend/server/restservice/search_test.go index 33b324abd96498bdfffac51742a754553c15187e..54413a2b00b89bcd9df1469f84f030fb2a524641 100644 --- a/backend/server/restservice/search_test.go +++ b/backend/server/restservice/search_test.go @@ -6,7 +6,6 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/require" - agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" diff --git a/backend/server/restservice/settings.go b/backend/server/restservice/settings.go index 8417b53e68bfe5de6512d06450d2c22709ac24a4..821392859496c6a532e770f1680ffa95466880ad 100644 --- a/backend/server/restservice/settings.go +++ b/backend/server/restservice/settings.go @@ -6,7 +6,6 @@ import ( "github.com/go-openapi/runtime/middleware" log "github.com/sirupsen/logrus" - dbmodel "isc.org/stork/server/database/model" "isc.org/stork/server/gen/models" "isc.org/stork/server/gen/restapi/operations/settings" @@ -14,7 +13,7 @@ import ( // Get global settings. func (r *RestAPI) GetSettings(ctx context.Context, params settings.GetSettingsParams) middleware.Responder { - dbSettingsMap, err := dbmodel.GetAllSettings(r.Db) + dbSettingsMap, err := dbmodel.GetAllSettings(r.DB) if err != nil { msg := "cannot get global settings" log.Error(err) @@ -55,37 +54,37 @@ func (r *RestAPI) UpdateSettings(ctx context.Context, params settings.UpdateSett Message: &msg, }) - err := dbmodel.SetSettingInt(r.Db, "bind9_stats_puller_interval", s.Bind9StatsPullerInterval) + err := dbmodel.SetSettingInt(r.DB, "bind9_stats_puller_interval", s.Bind9StatsPullerInterval) if err != nil { log.Error(err) return errRsp } - err = dbmodel.SetSettingStr(r.Db, "grafana_url", s.GrafanaURL) + err = dbmodel.SetSettingStr(r.DB, "grafana_url", s.GrafanaURL) if err != nil { log.Error(err) return errRsp } - err = dbmodel.SetSettingInt(r.Db, "kea_hosts_puller_interval", s.KeaHostsPullerInterval) + err = dbmodel.SetSettingInt(r.DB, "kea_hosts_puller_interval", s.KeaHostsPullerInterval) if err != nil { log.Error(err) return errRsp } - err = dbmodel.SetSettingInt(r.Db, "kea_stats_puller_interval", s.KeaStatsPullerInterval) + err = dbmodel.SetSettingInt(r.DB, "kea_stats_puller_interval", s.KeaStatsPullerInterval) if err != nil { log.Error(err) return errRsp } - err = dbmodel.SetSettingInt(r.Db, "kea_status_puller_interval", s.KeaStatusPullerInterval) + err = dbmodel.SetSettingInt(r.DB, "kea_status_puller_interval", s.KeaStatusPullerInterval) if err != nil { log.Error(err) return errRsp } - err = dbmodel.SetSettingInt(r.Db, "apps_state_puller_interval", s.KeaStatusPullerInterval) + err = dbmodel.SetSettingInt(r.DB, "apps_state_puller_interval", s.KeaStatusPullerInterval) if err != nil { log.Error(err) return errRsp } - err = dbmodel.SetSettingStr(r.Db, "prometheus_url", s.PrometheusURL) + err = dbmodel.SetSettingStr(r.DB, "prometheus_url", s.PrometheusURL) if err != nil { log.Error(err) return errRsp diff --git a/backend/server/restservice/settings_test.go b/backend/server/restservice/settings_test.go index 19a54389067529c80f5460f4b2fe313f51d86ea0..cbc16d14a7e354a07586211ff6d4a30f12f758e0 100644 --- a/backend/server/restservice/settings_test.go +++ b/backend/server/restservice/settings_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/stretchr/testify/require" - agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" diff --git a/backend/server/restservice/subnets.go b/backend/server/restservice/subnets.go index 3d44713d6689ad9bb1c9931edd7418dd670e2057..2f769ea371ed8b86b01986ddf1b0f7db42ed70dc 100644 --- a/backend/server/restservice/subnets.go +++ b/backend/server/restservice/subnets.go @@ -7,7 +7,6 @@ import ( "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/strfmt" log "github.com/sirupsen/logrus" - dbmodel "isc.org/stork/server/database/model" "isc.org/stork/server/gen/models" dhcp "isc.org/stork/server/gen/restapi/operations/d_h_c_p" @@ -46,7 +45,7 @@ func subnetToRestAPI(sn *dbmodel.Subnet) *models.Subnet { func (r *RestAPI) getSubnets(offset, limit, appID, family int64, filterText *string, sortField string, sortDir dbmodel.SortDirEnum) (*models.Subnets, error) { // get subnets from db - dbSubnets, total, err := dbmodel.GetSubnetsByPage(r.Db, offset, limit, appID, family, filterText, sortField, sortDir) + dbSubnets, total, err := dbmodel.GetSubnetsByPage(r.DB, offset, limit, appID, family, filterText, sortField, sortDir) if err != nil { return nil, err } @@ -104,7 +103,7 @@ func (r *RestAPI) GetSubnets(ctx context.Context, params dhcp.GetSubnetsParams) func (r *RestAPI) getSharedNetworks(offset, limit, appID, family int64, filterText *string, sortField string, sortDir dbmodel.SortDirEnum) (*models.SharedNetworks, error) { // get shared networks from db - dbSharedNetworks, total, err := dbmodel.GetSharedNetworksByPage(r.Db, offset, limit, appID, family, filterText, sortField, sortDir) + dbSharedNetworks, total, err := dbmodel.GetSharedNetworksByPage(r.DB, offset, limit, appID, family, filterText, sortField, sortDir) if err != nil { return nil, err } diff --git a/backend/server/restservice/subnets_test.go b/backend/server/restservice/subnets_test.go index f326282e84a99f2c712b846d0ba1bdaa904342ca..ea0d129819d0dd7854d29d60daa08adf5f9ea060 100644 --- a/backend/server/restservice/subnets_test.go +++ b/backend/server/restservice/subnets_test.go @@ -5,7 +5,6 @@ import ( "testing" "github.com/stretchr/testify/require" - agentcommtest "isc.org/stork/server/agentcomm/test" dbmodel "isc.org/stork/server/database/model" dbtest "isc.org/stork/server/database/test" @@ -262,9 +261,11 @@ func TestGetSubnets(t *testing.T) { require.EqualValues(t, 3, okRsp.Payload.Total) // checking if returned subnet-ids have expected values require.ElementsMatch(t, []int64{3, 4, 21}, - []int64{okRsp.Payload.Items[0].LocalSubnets[0].ID, + []int64{ + okRsp.Payload.Items[0].LocalSubnets[0].ID, okRsp.Payload.Items[1].LocalSubnets[0].ID, - okRsp.Payload.Items[2].LocalSubnets[0].ID}) + okRsp.Payload.Items[2].LocalSubnets[0].ID, + }) // get v4 subnets var dhcpVer int64 = 4 @@ -293,9 +294,11 @@ func TestGetSubnets(t *testing.T) { require.EqualValues(t, 3, okRsp.Payload.Total) // checking if returned subnet-ids have expected values require.ElementsMatch(t, []int64{2, 4, 21}, - []int64{okRsp.Payload.Items[0].LocalSubnets[0].ID, + []int64{ + okRsp.Payload.Items[0].LocalSubnets[0].ID, okRsp.Payload.Items[1].LocalSubnets[0].ID, - okRsp.Payload.Items[2].LocalSubnets[0].ID}) + okRsp.Payload.Items[2].LocalSubnets[0].ID, + }) // get subnets by text '118.0.0/2' text := "118.0.0/2" diff --git a/backend/server/restservice/users.go b/backend/server/restservice/users.go index f01c48bab4d16c1a2630703e6085343058ff0220..01fd02c7d8f658217d8e259a931c522296c370db 100644 --- a/backend/server/restservice/users.go +++ b/backend/server/restservice/users.go @@ -9,7 +9,6 @@ import ( "github.com/go-openapi/runtime/middleware" "github.com/pkg/errors" log "github.com/sirupsen/logrus" - dbmodel "isc.org/stork/server/database/model" "isc.org/stork/server/gen/models" "isc.org/stork/server/gen/restapi/operations/users" @@ -67,7 +66,7 @@ func (r *RestAPI) CreateSession(ctx context.Context, params users.CreateSessionP user.Password = *params.Credentials.Userpassword } - ok, err := dbmodel.Authenticate(r.Db, user) + ok, err := dbmodel.Authenticate(r.DB, user) if ok { err = r.SessionManager.LoginHandler(ctx, user) } @@ -94,7 +93,7 @@ func (r *RestAPI) DeleteSession(ctx context.Context, params users.DeleteSessionP } func (r *RestAPI) getUsers(offset, limit int64, filterText *string, sortField string, sortDir dbmodel.SortDirEnum) (*models.Users, error) { - dbUsers, total, err := dbmodel.GetUsersByPage(r.Db, offset, limit, filterText, sortField, sortDir) + dbUsers, total, err := dbmodel.GetUsersByPage(r.DB, offset, limit, filterText, sortField, sortDir) if err != nil { return nil, err } @@ -141,7 +140,7 @@ func (r *RestAPI) GetUsers(ctx context.Context, params users.GetUsersParams) mid // Returns user information by user ID. func (r *RestAPI) GetUser(ctx context.Context, params users.GetUserParams) middleware.Responder { id := int(params.ID) - su, err := dbmodel.GetUserByID(r.Db, id) + su, err := dbmodel.GetUserByID(r.DB, id) if err != nil { log.WithFields(log.Fields{ "userid": id, @@ -176,7 +175,7 @@ func (r *RestAPI) CreateUser(ctx context.Context, params users.CreateUserParams) if params.Account == nil { log.Warnf("failed to create new user account: missing data") - msg := fmt.Sprintf("failed to create new user account: missing data") + msg := "failed to create new user account: missing data" rspErr := models.APIError{ Message: &msg, } @@ -188,7 +187,7 @@ func (r *RestAPI) CreateUser(ctx context.Context, params users.CreateUserParams) if u == nil || u.Login == nil || u.Email == nil || u.Lastname == nil || u.Name == nil { log.Warnf("failed to create new user account: missing data") - msg := fmt.Sprintf("failed to create new user account: missing data") + msg := "failed to create new user account: missing data" rspErr := models.APIError{ Message: &msg, } @@ -207,7 +206,7 @@ func (r *RestAPI) CreateUser(ctx context.Context, params users.CreateUserParams) su.Groups = append(su.Groups, &dbmodel.SystemGroup{ID: int(gid)}) } - con, err := dbmodel.CreateUser(r.Db, su) + con, err := dbmodel.CreateUser(r.DB, su) if err != nil { if con { log.WithFields(log.Fields{ @@ -239,7 +238,7 @@ func (r *RestAPI) UpdateUser(ctx context.Context, params users.UpdateUserParams) if params.Account == nil { log.Warnf("failed to update user account: missing data") - msg := fmt.Sprintf("failed to update user account: missing data") + msg := "failed to update user account: missing data" rspErr := models.APIError{ Message: &msg, } @@ -251,7 +250,7 @@ func (r *RestAPI) UpdateUser(ctx context.Context, params users.UpdateUserParams) if u == nil || u.ID == nil || u.Login == nil || u.Email == nil || u.Lastname == nil || u.Name == nil { log.Warnf("failed to update user account: missing data") - msg := fmt.Sprintf("failed to update user account: missing data") + msg := "failed to update user account: missing data" rspErr := models.APIError{ Message: &msg, } @@ -271,7 +270,7 @@ func (r *RestAPI) UpdateUser(ctx context.Context, params users.UpdateUserParams) su.Groups = append(su.Groups, &dbmodel.SystemGroup{ID: int(gid)}) } - con, err := dbmodel.UpdateUser(r.Db, su) + con, err := dbmodel.UpdateUser(r.DB, su) if con { log.WithFields(log.Fields{ "userid": *u.ID, @@ -320,7 +319,7 @@ func (r *RestAPI) UpdateUserPassword(ctx context.Context, params users.UpdateUse // Try to change the password for the given user id. Including old password // for verification and the new password which will only be set if this // verification is successful. - auth, err := dbmodel.ChangePassword(r.Db, id, string(passwords.Oldpassword), + auth, err := dbmodel.ChangePassword(r.DB, id, string(passwords.Oldpassword), string(passwords.Newpassword)) // Error is returned when something went wrong with the database communication @@ -353,7 +352,7 @@ func (r *RestAPI) UpdateUserPassword(ctx context.Context, params users.UpdateUse } func (r *RestAPI) getGroups(offset, limit int64, filterText *string, sortField string, sortDir dbmodel.SortDirEnum) (*models.Groups, error) { - dbGroups, total, err := dbmodel.GetGroupsByPage(r.Db, offset, limit, filterText, sortField, sortDir) + dbGroups, total, err := dbmodel.GetGroupsByPage(r.DB, offset, limit, filterText, sortField, sortDir) if err != nil { return nil, err } diff --git a/backend/server/restservice/users_test.go b/backend/server/restservice/users_test.go index e9edbc376bb655ffb7a86e90d788cf3bdd5d3506..23a3fd583cfcccec263c0479520083c53bfbfc7b 100644 --- a/backend/server/restservice/users_test.go +++ b/backend/server/restservice/users_test.go @@ -381,7 +381,7 @@ func TestGetUser(t *testing.T) { // require.Len(t, okRsp.Payload.Groups, 1) } -// Tests that +// Tests that new session can be created for a logged user. func TestCreateSession(t *testing.T) { db, dbSettings, teardown := dbtest.SetupDatabaseTestCase(t) defer teardown() diff --git a/backend/server/server.go b/backend/server/server.go index a965058c8bb02e57b9488fccf0e5dd18eb17f143..d9b66b46af241b0ea64185f2c0e3f7e44b98827d 100644 --- a/backend/server/server.go +++ b/backend/server/server.go @@ -1,12 +1,12 @@ package server import ( + "errors" "fmt" "os" flags "github.com/jessevdk/go-flags" log "github.com/sirupsen/logrus" - "isc.org/stork" "isc.org/stork/server/agentcomm" "isc.org/stork/server/apps" @@ -18,10 +18,10 @@ import ( "isc.org/stork/server/restservice" ) -// Global Stork Server state +// Global Stork Server state. type StorkServer struct { - DbSettings dbops.DatabaseSettings - Db *dbops.PgDB + DBSettings dbops.DatabaseSettings + DB *dbops.PgDB AgentsSettings agentcomm.AgentsSettings Agents agentcomm.ConnectedAgents @@ -51,7 +51,7 @@ func (ss *StorkServer) ParseArgs() { parser.LongDescription = "Stork Server is a Kea and BIND 9 Dashboard" // Process Database specific args. - _, err := parser.AddGroup("Database ConnectionFlags", "", &ss.DbSettings) + _, err := parser.AddGroup("Database ConnectionFlags", "", &ss.DBSettings) if err != nil { log.Fatalf("FATAL error: %+v", err) } @@ -71,8 +71,9 @@ func (ss *StorkServer) ParseArgs() { // Do args parsing. if _, err := parser.Parse(); err != nil { code := 1 - if fe, ok := err.(*flags.Error); ok { - if fe.Type == flags.ErrHelp { + var flagsError *flags.Error + if errors.As(err, &flagsError) { + if flagsError.Type == flags.ErrHelp { code = 0 } } @@ -86,25 +87,25 @@ func (ss *StorkServer) ParseArgs() { } } -// Init for Stork Server state +// Init for Stork Server state. func NewStorkServer() (ss *StorkServer, err error) { ss = &StorkServer{} ss.ParseArgs() // setup database connection - ss.Db, err = dbops.NewPgDB(&ss.DbSettings) + ss.DB, err = dbops.NewPgDB(&ss.DBSettings) if err != nil { return nil, err } // initialize stork settings - err = dbmodel.InitializeSettings(ss.Db) + err = dbmodel.InitializeSettings(ss.DB) if err != nil { return nil, err } // setup event center - ss.EventCenter = eventcenter.NewEventCenter(ss.Db) + ss.EventCenter = eventcenter.NewEventCenter(ss.DB) // setup connected agents ss.Agents = agentcomm.NewConnectedAgents(&ss.AgentsSettings, ss.EventCenter) @@ -117,50 +118,50 @@ func NewStorkServer() (ss *StorkServer, err error) { // }() // initialize stork statistics - err = dbmodel.InitializeStats(ss.Db) + err = dbmodel.InitializeStats(ss.DB) if err != nil { return nil, err } // setup apps state puller - ss.AppsStatePuller, err = apps.NewStatePuller(ss.Db, ss.Agents, ss.EventCenter) + ss.AppsStatePuller, err = apps.NewStatePuller(ss.DB, ss.Agents, ss.EventCenter) if err != nil { return nil, err } // setup bind9 stats puller - ss.Bind9StatsPuller, err = bind9.NewStatsPuller(ss.Db, ss.Agents, ss.EventCenter) + ss.Bind9StatsPuller, err = bind9.NewStatsPuller(ss.DB, ss.Agents, ss.EventCenter) if err != nil { return nil, err } // setup kea stats puller - ss.KeaStatsPuller, err = kea.NewStatsPuller(ss.Db, ss.Agents) + ss.KeaStatsPuller, err = kea.NewStatsPuller(ss.DB, ss.Agents) if err != nil { return nil, err } // Setup Kea hosts puller. - ss.KeaHostsPuller, err = kea.NewHostsPuller(ss.Db, ss.Agents) + ss.KeaHostsPuller, err = kea.NewHostsPuller(ss.DB, ss.Agents) if err != nil { return nil, err } // Setup Kea HA status puller. - ss.HAStatusPuller, err = kea.NewHAStatusPuller(ss.Db, ss.Agents) + ss.HAStatusPuller, err = kea.NewHAStatusPuller(ss.DB, ss.Agents) if err != nil { return nil, err } // setup ReST API service - r, err := restservice.NewRestAPI(&ss.RestAPISettings, &ss.DbSettings, ss.Db, ss.Agents, ss.EventCenter) + r, err := restservice.NewRestAPI(&ss.RestAPISettings, &ss.DBSettings, ss.DB, ss.Agents, ss.EventCenter) if err != nil { ss.HAStatusPuller.Shutdown() ss.KeaHostsPuller.Shutdown() ss.KeaStatsPuller.Shutdown() ss.Bind9StatsPuller.Shutdown() ss.AppsStatePuller.Shutdown() - ss.Db.Close() + ss.DB.Close() return nil, err } ss.RestAPI = r @@ -170,7 +171,7 @@ func NewStorkServer() (ss *StorkServer, err error) { return ss, nil } -// Run Stork Server +// Run Stork Server. func (ss *StorkServer) Serve() { // Start listening for requests from ReST API. err := ss.RestAPI.Serve() @@ -179,7 +180,7 @@ func (ss *StorkServer) Serve() { } } -// Shutdown for Stork Server state +// Shutdown for Stork Server state. func (ss *StorkServer) Shutdown() { ss.EventCenter.AddInfoEvent("shutting down Stork server") log.Println("Shutting down Stork Server") @@ -191,6 +192,6 @@ func (ss *StorkServer) Shutdown() { ss.AppsStatePuller.Shutdown() ss.Agents.Shutdown() ss.EventCenter.Shutdown() - ss.Db.Close() + ss.DB.Close() log.Println("Stork Server shut down") } diff --git a/backend/server/server_test.go b/backend/server/server_test.go index 8dbb5ac67f970e49db084efbbc081589f54fc8f4..47f011be17aef3601f5390d129146168cb8c2008 100644 --- a/backend/server/server_test.go +++ b/backend/server/server_test.go @@ -9,11 +9,10 @@ import ( "testing" "github.com/stretchr/testify/require" - "isc.org/stork" ) -// Aux function checks if a list of expected strings is present in the string +// Aux function checks if a list of expected strings is present in the string. func checkOutput(output string, exp []string, reason string) bool { for _, x := range exp { fmt.Printf("Checking if %s exists in %s.\n", x, reason) @@ -27,20 +26,22 @@ func checkOutput(output string, exp []string, reason string) bool { // This is the list of all parameters we expect to see there. func getExpectedSwitches() []string { - return []string{"-v", "--version", "-d", "--db-name", "-u", "--db-user", "--db-host", + return []string{ + "-v", "--version", "-d", "--db-name", "-u", "--db-user", "--db-host", "-p", "--db-port", "--db-trace-queries", "--rest-cleanup-timeout", "--rest-graceful-timeout", "--rest-max-header-size", "--rest-host", "--rest-port", "--rest-listen-limit", "--rest-keep-alive", "--rest-read-timeout", "--rest-write-timeout", "--rest-tls-certificate", - "--rest-tls-key", "--rest-tls-ca", "--rest-static-files-dir"} + "--rest-tls-key", "--rest-tls-ca", "--rest-static-files-dir", + } } -// Location of the stork-server binary +// Location of the stork-server binary. const ServerBin = "../cmd/stork-server/stork-server" -// Location of the stork-server man page +// Location of the stork-server man page. const AgentMan = "../../doc/man/stork-server.8.rst" -// This test checks if stork-agent -h reports all expected command-line switches +// This test checks if stork-agent -h reports all expected command-line switches. func TestCommandLineSwitches(t *testing.T) { // Run the --help version and get its output. agentCmd := exec.Command(ServerBin, "-h") @@ -51,7 +52,7 @@ func TestCommandLineSwitches(t *testing.T) { require.True(t, checkOutput(string(output), getExpectedSwitches(), "stork-agent -h output")) } -// This test checks if all expected command-line switches are documented +// This test checks if all expected command-line switches are documented. func TestCommandLineSwitchesDoc(t *testing.T) { // Read the contents of the man page file, err := os.Open(AgentMan) diff --git a/backend/server/test/fake_eventcenter.go b/backend/server/test/fake_eventcenter.go index a610bcecdd28e6808ee3285ca1a28714dd62020d..d510ad3910c335833b02c1813035575ddf515e14 100644 --- a/backend/server/test/fake_eventcenter.go +++ b/backend/server/test/fake_eventcenter.go @@ -12,13 +12,18 @@ type FakeEventCenter struct { func (fec *FakeEventCenter) AddInfoEvent(text string, objects ...interface{}) { } + func (fec *FakeEventCenter) AddWarningEvent(text string, objects ...interface{}) { } + func (fec *FakeEventCenter) AddErrorEvent(text string, objects ...interface{}) { } + func (fec *FakeEventCenter) AddEvent(event *dbmodel.Event) { } + func (fec *FakeEventCenter) Shutdown() { } + func (fec *FakeEventCenter) ServeHTTP(w http.ResponseWriter, req *http.Request) { } diff --git a/backend/util/util.go b/backend/util/util.go index 2a196ce69fad25599036c671d66fb101bcc38038..c88ea99e522f1cee821336db3d62f8e1d245f7be 100644 --- a/backend/util/util.go +++ b/backend/util/util.go @@ -1,7 +1,6 @@ package storkutil import ( - "errors" "fmt" "net" "os" @@ -13,6 +12,7 @@ import ( "strings" "time" + "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -54,7 +54,7 @@ func MakeCIDR(address string) (string, error) { if !strings.Contains(address, "/") { ip := net.ParseIP(address) if ip == nil { - return address, errors.New("provided string %s is not a valid IP address") + return address, errors.Errorf("provided string %s is not a valid IP address", address) } ip4 := ip.To4() if ip4 != nil { @@ -95,7 +95,7 @@ func SetupLogging() { FullTimestamp: true, TimestampFormat: "2006-01-02 15:04:05", // TODO: do more research and enable if it brings value - //PadLevelText: true, + // PadLevelText: true, // FieldMap: log.FieldMap{ // FieldKeyTime: "@timestamp", // FieldKeyLevel: "@level", @@ -109,7 +109,7 @@ func SetupLogging() { }) } -// helper code for mocking os/exec stuff... pathetic +// helper code for mocking os/exec stuff... pathetic. type Commander interface { Output(string, ...string) ([]byte, error) }