From 5acc64de599e73c458ea97f5b38dc88cb74cd7dd Mon Sep 17 00:00:00 2001 From: Stanislav Nikitin Date: Wed, 16 Oct 2019 18:32:21 +0000 Subject: [PATCH] Drone CI and linting (#14) --- .drone.yml | 23 +++++++++++++++-------- Dockerfile | 3 ++- cmd/giredored/main.go | 2 ++ domains/client/v1/config.go | 2 ++ domains/client/v1/packages.go | 3 +++ domains/server/v1/goimports.go | 2 ++ domains/server/v1/packagesapi.go | 2 ++ internal/configuration/fileconfig.go | 5 +++++ internal/httpserver/exported.go | 13 ++++++++++++- internal/httpserver/strictjson.go | 1 + internal/logger/exported.go | 5 ++++- internal/requester/exported.go | 1 + 12 files changed, 51 insertions(+), 11 deletions(-) diff --git a/.drone.yml b/.drone.yml index b3c1d40..5bff75e 100644 --- a/.drone.yml +++ b/.drone.yml @@ -5,29 +5,31 @@ name: build steps: - name: notify-start - image: appleboy/drone-discord + image: pztrn/discordrone settings: webhook_id: from_secret: discord_webhook_id webhook_token: from_secret: discord_webhook_secret - message: 'Starting building **{{repo.name}}#{{build.number}}@{{build.commit}}** @ {{datetime build.started "02-Jan-2006 15:04:05 MST" "Asia/Yekaterinburg"}} (See {{build.link}} for logs).' + message: 'Starting building **{{repo.name}}#{{build.number}}@{{commit.sha}}** @ {{datetime build.started "02-Jan-2006 15:04:05 MST" "Asia/Yekaterinburg"}} (See {{build.link}} for logs).' - name: lint image: golangci/golangci-lint:latest environment: - GOFLAGS: -mod=vendor CGO_ENABLED: 0 commands: - golangci-lint run + depends_on: + - notify-start - name: test image: golang:1.13.1-alpine environment: - GOFLAGS: -mod=vendor CGO_ENABLED: 0 commands: - go test ./... + depends_on: + - notify-start - name: docker image: plugins/docker @@ -41,13 +43,16 @@ steps: from_secret: dockerhub_password repo: pztrn/giredore auto_tag: true + depends_on: + - lint + - test - name: notify-end when: status: - success - failure - image: appleboy/drone-discord + image: pztrn/discordrone settings: webhook_id: from_secret: discord_webhook_id @@ -55,7 +60,9 @@ steps: from_secret: discord_webhook_secret message: " {{#success build.status}} - **{{repo.name}}#{{build.number}}@{{build.commit}}** built and pushed to hub.docker.com. + **{{repo.name}}#{{build.number}}@{{commit.sha}}** built in {{since build.startedint}} and pushed to hub.docker.com. {{ else }} - **{{repo.name}}#{{build.number}}@{{build.commit}}** failed. See {{build.link}}. - {{/success}}" \ No newline at end of file + **{{repo.name}}#{{build.number}}@{{commit.sha}}** failed. See {{build.link}}. + {{/success}}" + depends_on: + - docker \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 3b4832e..8eff37c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,8 @@ FROM golang:1.13.1-alpine AS build WORKDIR /go/src/sources.dev.pztrn.name/pztrn/giredore COPY . . -RUN cd /go/src/sources.dev.pztrn.name/pztrn/giredore/cmd/giredored && go build && cd ../giredorectl && go build +ENV CGO_ENABLED=0 +RUN cd /go/src/sources.dev.pztrn.name/pztrn/giredore/cmd/giredored && go build -tags netgo -ldflags '-w -extldflags "-static"' && cd ../giredorectl && go build -tags netgo -ldflags '-w -extldflags "-static"' FROM alpine:latest LABEL maintainer "Stanislav N. " diff --git a/cmd/giredored/main.go b/cmd/giredored/main.go index 0d90e02..9df5d1b 100644 --- a/cmd/giredored/main.go +++ b/cmd/giredored/main.go @@ -29,7 +29,9 @@ func main() { // CTRL+C handler. signalHandler := make(chan os.Signal, 1) shutdownDone := make(chan bool, 1) + signal.Notify(signalHandler, os.Interrupt, syscall.SIGTERM) + go func() { <-signalHandler httpserver.Shutdown() diff --git a/domains/client/v1/config.go b/domains/client/v1/config.go index be0efed..0691216 100644 --- a/domains/client/v1/config.go +++ b/domains/client/v1/config.go @@ -11,6 +11,7 @@ import ( func GetConfiguration(options map[string]string) { url := "http://" + options["server"] + "/_api/configuration" + log.Info().Msg("Getting configuration from giredore server...") data, err := requester.Get(url) @@ -23,6 +24,7 @@ func GetConfiguration(options map[string]string) { func SetAllowedIPs(args []string, options map[string]string) { url := "http://" + options["server"] + "/_api/configuration/allowedips" + log.Info().Str("allowed IPs", args[0]).Msg("Setting allowed IPs for API interaction...") req := &structs.AllowedIPsSetRequest{ diff --git a/domains/client/v1/packages.go b/domains/client/v1/packages.go index 772baab..cf10860 100644 --- a/domains/client/v1/packages.go +++ b/domains/client/v1/packages.go @@ -17,6 +17,7 @@ func DeletePackage(args []string, options map[string]string) { log.Info().Str("original path", req.OriginalPath).Msg("Sending package deletion request to giredored...") url := "http://" + options["server"] + "/_api/packages" + data, err := requester.Delete(url, req) if err != nil { log.Fatal().Err(err).Msg("Failed to send package deletion request to giredored") @@ -36,6 +37,7 @@ func GetPackages(args []string, options map[string]string) { } url := "http://" + options["server"] + "/_api/packages" + log.Info().Msg("Getting packages data from giredore server...") data, err := requester.Post(url, req) @@ -57,6 +59,7 @@ func SetPackage(args []string, options map[string]string) { log.Info().Str("description", pkg.Description).Str("original path", pkg.OriginalPath).Str("real path", pkg.RealPath).Str("VCS", pkg.VCS).Msg("Sending set/update request to giredored...") url := "http://" + options["server"] + "/_api/packages" + data, err := requester.Put(url, pkg) if err != nil { log.Fatal().Err(err).Msg("Failed to send package update/set request to giredored") diff --git a/domains/server/v1/goimports.go b/domains/server/v1/goimports.go index 6a9c50f..ba7dd23 100644 --- a/domains/server/v1/goimports.go +++ b/domains/server/v1/goimports.go @@ -18,7 +18,9 @@ func throwGoImports(ec echo.Context) error { // to list available packages. // For now only package itself is supported, all other features in ToDo. packageNameRaw := ec.Request().URL.Path + pkgs, errs := configuration.Cfg.GetPackagesInfo([]string{packageNameRaw}) + if errs != nil { log.Error().Str("package", packageNameRaw).Msgf("Failed to get package information: %+v", errs) return ec.JSON(http.StatusBadRequest, &structs.Reply{Status: structs.StatusFailure, Errors: errs}) diff --git a/domains/server/v1/packagesapi.go b/domains/server/v1/packagesapi.go index dd9c3b9..c9f9e31 100644 --- a/domains/server/v1/packagesapi.go +++ b/domains/server/v1/packagesapi.go @@ -24,7 +24,9 @@ func packagesGET(ec echo.Context) error { log.Info().Msgf("Received package(s) info get request: %+v", req) var pkgs map[string]*structs.Package + var errors []structs.Error + if req.All { pkgs = configuration.Cfg.GetAllPackagesInfo() } else { diff --git a/internal/configuration/fileconfig.go b/internal/configuration/fileconfig.go index 3c2e0ca..8739d4d 100644 --- a/internal/configuration/fileconfig.go +++ b/internal/configuration/fileconfig.go @@ -62,6 +62,7 @@ func (fc *fileConfig) DeletePackage(req *structs.PackageDeleteRequest) []structs func (fc *fileConfig) GetAllowedIPs() []string { var allowedIPs []string + fc.HTTP.allowedipsmutex.RLock() allowedIPs = append(allowedIPs, fc.HTTP.AllowedIPs...) fc.HTTP.allowedipsmutex.RUnlock() @@ -83,6 +84,7 @@ func (fc *fileConfig) GetAllPackagesInfo() map[string]*structs.Package { func (fc *fileConfig) GetPackagesInfo(packages []string) (map[string]*structs.Package, []structs.Error) { pkgs := make(map[string]*structs.Package) + var errors []structs.Error fc.packagesMutex.Lock() @@ -135,6 +137,7 @@ func (fc *fileConfig) Initialize() { // Ensure that localhost (127.0.0.1) are defined in AllowedIPs. var localhostIsAllowed bool + for _, ip := range fc.HTTP.AllowedIPs { if strings.Contains(ip, "127.0.0.1") { localhostIsAllowed = true @@ -144,6 +147,7 @@ func (fc *fileConfig) Initialize() { if !localhostIsAllowed { cfgLoadLog.Warn().Msg("Localhost (127.0.0.1) wasn't allowed to access configuration API, adding it to list of allowed IP addresses") + fc.HTTP.AllowedIPs = append(fc.HTTP.AllowedIPs, "127.0.0.1") } else { cfgLoadLog.Debug().Msg("Localhost (127.0.0.1) is allowed to access configuration API") @@ -161,6 +165,7 @@ func (fc *fileConfig) normalizePath(configPath string) (string, error) { if err != nil { return "", err } + configPath = strings.Replace(configPath, "~", homeDir, 1) } diff --git a/internal/httpserver/exported.go b/internal/httpserver/exported.go index 72067a3..858b4b7 100644 --- a/internal/httpserver/exported.go +++ b/internal/httpserver/exported.go @@ -44,10 +44,12 @@ func Initialize() { // Shutdown stops HTTP server. Returns true on success and false on failure. func Shutdown() { log.Info().Msg("Shutting down HTTP server...") + err := Srv.Shutdown(context.Background()) if err != nil { log.Fatal().Err(err).Msg("Failed to stop HTTP server") } + log.Info().Msg("HTTP server shutted down") } @@ -59,19 +61,23 @@ func Start() { go func() { err := Srv.Start(configuration.Cfg.HTTP.Listen) if !strings.Contains(err.Error(), "Server closed") { - log.Fatal().Err(err).Msg("HTTP server critial error occurred") + log.Fatal().Err(err).Msg("HTTP server critical error occurred") } }() // Check that HTTP server was started. httpc := &http.Client{Timeout: time.Second * 1} checks := 0 + for { checks++ + if checks >= configuration.Cfg.HTTP.WaitForSeconds { log.Fatal().Int("seconds passed", checks).Msg("HTTP server isn't up") } + time.Sleep(time.Second * 1) + resp, err := httpc.Get("http://" + configuration.Cfg.HTTP.Listen + "/_internal/waitForOnline") if err != nil { log.Debug().Err(err).Msg("HTTP error occurred, HTTP server isn't ready, waiting...") @@ -80,10 +86,12 @@ func Start() { response, err := ioutil.ReadAll(resp.Body) resp.Body.Close() + if err != nil { log.Debug().Err(err).Msg("Failed to read response body, HTTP server isn't ready, waiting...") continue } + log.Debug().Str("status", resp.Status).Int("body length", len(response)).Msg("HTTP response received") if resp.StatusCode == http.StatusOK { @@ -91,7 +99,9 @@ func Start() { log.Debug().Msg("Response is empty, HTTP server isn't ready, waiting...") continue } + log.Debug().Int("status code", resp.StatusCode).Msgf("Response: %+v", string(response)) + if len(response) == 17 { break } @@ -104,5 +114,6 @@ func waitForHTTPServerToBeUpHandler(ec echo.Context) error { response := map[string]string{ "error": "None", } + return ec.JSON(200, response) } diff --git a/internal/httpserver/strictjson.go b/internal/httpserver/strictjson.go index b5c8eef..7574b93 100644 --- a/internal/httpserver/strictjson.go +++ b/internal/httpserver/strictjson.go @@ -24,6 +24,7 @@ func (sjb *StrictJSONBinder) Bind(i interface{}, c echo.Context) error { // Decode it. decoder := json.NewDecoder(req.Body) decoder.DisallowUnknownFields() + if err := decoder.Decode(i); err != nil { if ute, ok := err.(*json.UnmarshalTypeError); ok { return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Unmarshal type error: expected=%v, got=%v, field=%v, offset=%v", ute.Type, ute.Value, ute.Field, ute.Offset)) diff --git a/internal/logger/exported.go b/internal/logger/exported.go index fbbbb58..6889d05 100644 --- a/internal/logger/exported.go +++ b/internal/logger/exported.go @@ -23,6 +23,7 @@ func Initialize() { loggerLevel, loggerLevelFound := os.LookupEnv("LOGGER_LEVEL") if loggerLevelFound { fmt.Println("Setting logger level to:", loggerLevel) + switch strings.ToUpper(loggerLevel) { case "DEBUG": zerolog.SetGlobalLevel(zerolog.DebugLevel) @@ -36,7 +37,7 @@ func Initialize() { zerolog.SetGlobalLevel(zerolog.FatalLevel) default: fmt.Println("Invalid logger level passed:", loggerLevel) - fmt.Println("Fofcing INFO") + fmt.Println("Forcing INFO") zerolog.SetGlobalLevel(zerolog.InfoLevel) } } else { @@ -47,6 +48,7 @@ func Initialize() { output := zerolog.ConsoleWriter{Out: os.Stdout, NoColor: false, TimeFormat: time.RFC3339} output.FormatLevel = func(i interface{}) string { var v string + if ii, ok := i.(string); ok { ii = strings.ToUpper(ii) switch ii { @@ -66,6 +68,7 @@ func Initialize() { v = ii } } + return fmt.Sprintf("| %s |", v) } diff --git a/internal/requester/exported.go b/internal/requester/exported.go index 7bde2a1..9999932 100644 --- a/internal/requester/exported.go +++ b/internal/requester/exported.go @@ -52,6 +52,7 @@ func execRequest(method string, url string, data interface{}) ([]byte, error) { if err2 != nil { return nil, err2 } + response.Body.Close() log.Debug().Int("response body length (bytes)", len(bodyBytes)).Msg("Got response")