diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..a5f83a4 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,55 @@ +linters-settings: + govet: + check-shadowing: true + golint: + min-confidence: 0.8 + gocyclo: + min-complexity: 10 + max-complexity: 12 + maligned: + suggest-new: true + dupl: + threshold: 150 + goconst: + min-len: 2 + min-occurrences: 2 + misspell: + locale: US + lll: + line-length: 140 + goimports: + local-prefixes: github.com/golangci/golangci-lint + gocritic: + enabled-tags: + - performance + - style + - experimental + disabled-checks: + - wrapperFunc + - commentFormatting + +linters: + enable-all: true + disable: + - maligned + - prealloc + - gochecknoglobals + - goimports + +#run: +# skip-dirs: +# - test/testdata_etc + +issues: + exclude-use-default: false + exclude-rules: + - text: "weak cryptographic primitive" + linters: + - gosec + +# golangci.com configuration +# https://github.com/golangci/golangci/wiki/Configuration +service: + golangci-lint-version: 1.15.x # use the fixed version to not introduce new linters unexpectedly +# prepare: +# - echo "here I can run custom commands, but no preparation needed for this repo" diff --git a/.realize.yaml b/.realize.yaml new file mode 100755 index 0000000..9e00d99 --- /dev/null +++ b/.realize.yaml @@ -0,0 +1,25 @@ +settings: +server: + status: true + open: false + host: localhost + port: 5001 +schema: + - name: agent + path: agent + commands: + install: + status: false + build: + status: false + run: + status: true +# method: dlv debug -l=localhost:35173 --headless=true --api-version=2 --backend=default + watcher: + paths: + - / + ignore_paths: + - vendor + extensions: + - go + diff --git a/.travis.yml b/.travis.yml index 3794051..0187ed4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,16 @@ sudo: false language: go go: - - "1.10" + - "1.12.x" + +env: + - GO111MODULE=on before_script: - - make init-deps vendor + - make init-deps script: - - make build + - make checkstyle build after_success: - curl --request POST "https://goreportcard.com/checks" --data "repo=github.com/avarabyeu/goRP" diff --git a/Gopkg.lock b/Gopkg.lock deleted file mode 100644 index 0e2d03e..0000000 --- a/Gopkg.lock +++ /dev/null @@ -1,230 +0,0 @@ -# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. - - -[[projects]] - branch = "master" - digest = "1:454adc7f974228ff789428b6dc098638c57a64aa0718f0bd61e53d3cd39d7a75" - name = "github.com/chzyer/readline" - packages = ["."] - pruneopts = "UT" - revision = "2972be24d48e78746da79ba8e24e8b488c9880de" - -[[projects]] - digest = "1:a1038ef593beb4771c8f0f9c26e8b00410acd800af5c6864651d9bf160ea1813" - name = "github.com/hpcloud/tail" - packages = [ - ".", - "ratelimiter", - "util", - "watch", - "winfile", - ] - pruneopts = "UT" - revision = "a30252cb686a21eb2d0b98132633053ec2f7f1e5" - version = "v1.0.0" - -[[projects]] - branch = "master" - digest = "1:e51f40f0c19b39c1825eadd07d5c0a98a2ad5942b166d9fc4f54750ce9a04810" - name = "github.com/juju/ansiterm" - packages = [ - ".", - "tabwriter", - ] - pruneopts = "UT" - revision = "720a0952cc2ac777afc295d9861263e2a4cf96a1" - -[[projects]] - branch = "master" - digest = "1:bb08c7bb1c7224636b1a00639f079ed4391eb822945f26db74b8d8ee3f14d991" - name = "github.com/lunixbochs/vtclean" - packages = ["."] - pruneopts = "UT" - revision = "2d01aacdc34a083dca635ba869909f5fc0cd4f41" - -[[projects]] - branch = "master" - digest = "1:2d2bc0f23cca6b59cec3fbece9abc102bdb19f548dd58d7667e57699074a2c76" - name = "github.com/manifoldco/promptui" - packages = [ - ".", - "list", - "screenbuf", - ] - pruneopts = "UT" - revision = "157c96fb638a14d268b305cf2012582431fcc410" - -[[projects]] - digest = "1:c658e84ad3916da105a761660dcaeb01e63416c8ec7bc62256a9b411a05fcd67" - name = "github.com/mattn/go-colorable" - packages = ["."] - pruneopts = "UT" - revision = "167de6bfdfba052fa6b2d3664c8f5272e23c9072" - version = "v0.0.9" - -[[projects]] - digest = "1:d4d17353dbd05cb52a2a52b7fe1771883b682806f68db442b436294926bbfafb" - name = "github.com/mattn/go-isatty" - packages = ["."] - pruneopts = "UT" - revision = "0360b2af4f38e8d38c7fce2a9f4e702702d73a39" - version = "v0.0.3" - -[[projects]] - digest = "1:42e29deef12327a69123b9cb2cb45fee4af5c12c2a23c6e477338279a052703f" - name = "github.com/onsi/ginkgo" - packages = [ - ".", - "config", - "internal/codelocation", - "internal/containernode", - "internal/failer", - "internal/leafnodes", - "internal/remote", - "internal/spec", - "internal/spec_iterator", - "internal/specrunner", - "internal/suite", - "internal/testingtproxy", - "internal/writer", - "reporters", - "reporters/stenographer", - "reporters/stenographer/support/go-colorable", - "reporters/stenographer/support/go-isatty", - "types", - ] - pruneopts = "UT" - revision = "3774a09d95489ccaa16032e0770d08ea77ba6184" - version = "v1.6.0" - -[[projects]] - digest = "1:29f294e6a3b9d30629266b2765a8c203056387941e600405b8e8871c84653042" - name = "github.com/onsi/gomega" - packages = [ - ".", - "format", - "internal/assertion", - "internal/asyncassertion", - "internal/oraclematcher", - "internal/testingtsupport", - "matchers", - "matchers/support/goraph/bipartitegraph", - "matchers/support/goraph/edge", - "matchers/support/goraph/node", - "matchers/support/goraph/util", - "types", - ] - pruneopts = "UT" - revision = "b6ea1ea48f981d0f615a154a45eabb9dd466556d" - version = "v1.4.1" - -[[projects]] - branch = "master" - digest = "1:b06b8535976f710e79879a11eee35e0a06886ed51828bb212e7186b932b93e88" - name = "golang.org/x/net" - packages = [ - "html", - "html/atom", - "html/charset", - "idna", - "publicsuffix", - ] - pruneopts = "UT" - revision = "922f4815f713f213882e8ef45e0d315b164d705c" - -[[projects]] - branch = "master" - digest = "1:a3f00ac457c955fe86a41e1495e8f4c54cb5399d609374c5cc26aa7d72e542c8" - name = "golang.org/x/sys" - packages = ["unix"] - pruneopts = "UT" - revision = "3b58ed4ad3395d483fc92d5d14123ce2c3581fec" - -[[projects]] - digest = "1:436b24586f8fee329e0dd65fd67c817681420cda1d7f934345c13fe78c212a73" - name = "golang.org/x/text" - packages = [ - "collate", - "collate/build", - "encoding", - "encoding/charmap", - "encoding/htmlindex", - "encoding/internal", - "encoding/internal/identifier", - "encoding/japanese", - "encoding/korean", - "encoding/simplifiedchinese", - "encoding/traditionalchinese", - "encoding/unicode", - "internal/colltab", - "internal/gen", - "internal/tag", - "internal/triegen", - "internal/ucd", - "internal/utf8internal", - "language", - "runes", - "secure/bidirule", - "transform", - "unicode/bidi", - "unicode/cldr", - "unicode/norm", - "unicode/rangetable", - ] - pruneopts = "UT" - revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0" - version = "v0.3.0" - -[[projects]] - digest = "1:abeb38ade3f32a92943e5be54f55ed6d6e3b6602761d74b4aab4c9dd45c18abd" - name = "gopkg.in/fsnotify.v1" - packages = ["."] - pruneopts = "UT" - revision = "c2828203cd70a50dcccfb2761f8b1f8ceef9a8e9" - source = "https://github.com/fsnotify/fsnotify.git" - version = "v1.4.7" - -[[projects]] - digest = "1:cf9c32df6fe209f9b5db1aa91c6e4084d3867baa9063803df07c5b80a37f1f90" - name = "gopkg.in/resty.v1" - packages = ["."] - pruneopts = "UT" - revision = "97a15579492cd5f35632499f315d7a8df94160a1" - version = "v1.8.0" - -[[projects]] - branch = "v1" - digest = "1:0caa92e17bc0b65a98c63e5bc76a9e844cd5e56493f8fdbb28fad101a16254d9" - name = "gopkg.in/tomb.v1" - packages = ["."] - pruneopts = "UT" - revision = "dd632973f1e7218eb1089048e0798ec9ae7dceb8" - -[[projects]] - digest = "1:b24d38b282bacf9791408a080f606370efa3d364e4b5fd9ba0f7b87786d3b679" - name = "gopkg.in/urfave/cli.v1" - packages = ["."] - pruneopts = "UT" - revision = "cfb38830724cc34fedffe9a2a29fb54fa9169cd1" - version = "v1.20.0" - -[[projects]] - digest = "1:342378ac4dcb378a5448dd723f0784ae519383532f5e70ade24132c4c8693202" - name = "gopkg.in/yaml.v2" - packages = ["."] - pruneopts = "UT" - revision = "5420a8b6744d3b0345ab293f6fcba19c978f1183" - version = "v2.2.1" - -[solve-meta] - analyzer-name = "dep" - analyzer-version = 1 - input-imports = [ - "github.com/manifoldco/promptui", - "github.com/onsi/ginkgo", - "github.com/onsi/gomega", - "gopkg.in/resty.v1", - "gopkg.in/urfave/cli.v1", - ] - solver-name = "gps-cdcl" - solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml deleted file mode 100644 index 171b028..0000000 --- a/Gopkg.toml +++ /dev/null @@ -1,55 +0,0 @@ -# Gopkg.toml example -# -# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md -# for detailed Gopkg.toml documentation. -# -# required = ["github.com/user/thing/cmd/thing"] -# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] -# -# [[constraint]] -# name = "github.com/user/project" -# version = "1.0.0" -# -# [[constraint]] -# name = "github.com/user/project2" -# branch = "dev" -# source = "github.com/myfork/project2" -# -# [[override]] -# name = "github.com/x/y" -# version = "2.4.0" -# -# [prune] -# non-go = false -# go-tests = true -# unused-packages = true - - -[prune] - go-tests = true - unused-packages = true - -[[constraint]] - name = "gopkg.in/resty.v1" - version = "1.7.0" - -# Apply workaround from https://github.com/golang/dep/issues/1799 -[[override]] - name = "gopkg.in/fsnotify.v1" - source = "https://github.com/fsnotify/fsnotify.git" - -[[constraint]] - name = "gopkg.in/urfave/cli.v1" - version = "1.20.0" - -[[constraint]] - name = "github.com/onsi/ginkgo" - version = "1.4.0" - -[[constraint]] - name = "github.com/onsi/gomega" - version = "1.3.0" - -[[constraint]] - name = "github.com/manifoldco/promptui" - branch = "master" diff --git a/Makefile b/Makefile index 70b68f8..6ad85ec 100644 --- a/Makefile +++ b/Makefile @@ -17,21 +17,24 @@ help: @echo "checkstyle - gofmt+golint+misspell" init-deps: - $(if $(shell which dep 2>/dev/null),$(echo "Dep is already installed..."),$(shell go get -u github.com/golang/dep/cmd/dep)) - $(GO) get github.com/alecthomas/gometalinter - gometalinter --install + # installs gometalinter +# curl -L https://git.io/vp6lP | sh +# gometalinter --install + curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.15.0 -vendor: - dep ensure --vendor-only + +#vendor: +# dep ensure --vendor-only test: $(GO) test -cover ${GODIRS_NOVENDOR} checkstyle: - gometalinter --vendor ./... --fast --deadline 10m + bin/golangci-lint run --enable-all --deadline 10m ./... fmt: gofmt -l -w -s ${GOFILES_NOVENDOR} +# goimports -l -w . #build: checkstyle test build: @@ -51,3 +54,7 @@ tag: release: rm -rf dist goreleaser release + +grpc-gen: + #Learn here: https://jbrandhorst.com/post/go-protobuf-tips/ + protoc -I=. -I=vendor -I=${GOPATH}/src model/*.proto --go_out=plugins=grpc:. diff --git a/agent/handlers/controller.go b/agent/handlers/controller.go new file mode 100644 index 0000000..3465bdd --- /dev/null +++ b/agent/handlers/controller.go @@ -0,0 +1,186 @@ +package handlers + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + + "github.com/avarabyeu/goRP/agent/store" + "github.com/avarabyeu/goRP/gorp" + "github.com/go-chi/chi" + "github.com/go-chi/chi/middleware" + "github.com/gofrs/uuid" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" +) + +//NewMux creates new Mux/Controller +func NewMux(basePath string, client *gorp.Client, kvStore store.KVStore) http.Handler { + mux := chi.NewMux() + mux.Use(middleware.Heartbeat("/health")) + mux.Use(middleware.Recoverer) + mux.Use(middleware.Logger) + mux.Use(middleware.StripSlashes) + + // creates launch + mux.Post(fmt.Sprintf("%s/{project}/launch", basePath), startLaunchHandler(kvStore, client)) + + // finishes launch + mux.Put(fmt.Sprintf("%s/{project}/launch/{launchID}/finish", basePath), finishLaunchHandler(kvStore, client)) + + // creates root test item + mux.Post(fmt.Sprintf("%s/{project}/item", basePath), startRootItemHandler(client, kvStore)) + + // creates child test item + mux.Post(fmt.Sprintf("%s/{project}/item/{parentID}", basePath), startTestItemHandler(kvStore, client)) + + // finishes test item + mux.Put(fmt.Sprintf("%s/{project}/item/{itemID}", basePath), finishItemHandler(kvStore, client)) + + // creates log + mux.Post(fmt.Sprintf("%s/{project}/log", basePath), func(w http.ResponseWriter, rq *http.Request) { + }) + + return mux +} + +func finishItemHandler(kvStore store.KVStore, client *gorp.Client) http.HandlerFunc { + return JSONHandler(func(rq *http.Request) (interface{}, error) { + itemID := chi.URLParam(rq, "itemID") + realItemID, err := kvStore.FindString("uuids", itemID) + if err != nil { + return nil, NewStatusErr(http.StatusBadRequest, errors.New("Unable to find real request UUID")) + } + + body, err := ioutil.ReadAll(rq.Body) + if err != nil { + return nil, NewStatusErr(http.StatusInternalServerError, errors.New("Cannot read request body")) + } + + go func() { + if _, err := client.FinishTestRaw(realItemID, bytes.NewBuffer(body)); err != nil { + log.Error(err) + } + }() + + return &gorp.MsgRS{Msg: "Test Item has been finished"}, nil + }) +} + +func startTestItemHandler(kvStore store.KVStore, client *gorp.Client) http.HandlerFunc { + return JSONHandler(func(rq *http.Request) (interface{}, error) { + uid, err := uuid.NewV4() + if err != nil { + return nil, NewStatusErr(http.StatusInternalServerError, errors.Wrap(errors.New("ok"), "Unable to generate UUID")) + } + + parentID := chi.URLParam(rq, "parentID") + realParentID, err := kvStore.FindString("uuids", parentID) + if err != nil { + return nil, NewStatusErr(http.StatusBadRequest, errors.New("Unable to find request UUID")) + } + + body, err := ioutil.ReadAll(rq.Body) + if err != nil { + return nil, NewStatusErr(http.StatusInternalServerError, errors.New("Cannot read request body")) + } + + go func() { + rs, err := client.StartChildTestRaw(realParentID, bytes.NewBuffer(body)) + if err != nil { + if err := kvStore.Store("pending-item", uid.String(), body); err != nil { + log.Error(err) + } + } else { + if err := kvStore.Store("uuids", uid.String(), rs.ID); err != nil { + log.Error(err) + } + } + }() + + return &gorp.EntryCreatedRS{ID: uid.String()}, nil + }) +} + +func startRootItemHandler(client *gorp.Client, kvStore store.KVStore) http.HandlerFunc { + return JSONHandler(func(rq *http.Request) (interface{}, error) { + uid, err := uuid.NewV4() + if err != nil { + return nil, NewStatusErr(http.StatusInternalServerError, errors.Wrap(errors.New("ok"), "Unable to generate UUID")) + } + + body, err := ioutil.ReadAll(rq.Body) + if err != nil { + return nil, NewStatusErr(http.StatusInternalServerError, errors.New("Cannot read request body")) + } + + go func() { + rs, err := client.StartTestRaw(bytes.NewBuffer(body)) + if err != nil { + if err := kvStore.Store("pending-item", uid.String(), body); err != nil { + log.Error(err) + } + } else { + if err := kvStore.Store("uuids", uid.String(), rs.ID); err != nil { + log.Error(err) + } + } + }() + + return &gorp.EntryCreatedRS{ID: uid.String()}, nil + }) +} + +func finishLaunchHandler(kvStore store.KVStore, client *gorp.Client) http.HandlerFunc { + return JSONHandler(func(rq *http.Request) (interface{}, error) { + launchID := chi.URLParam(rq, "launchID") + realLaunchID, err := kvStore.FindString("uuids", launchID) + if err != nil { + return nil, NewStatusErr(http.StatusBadRequest, errors.New("Unable to find request UUID")) + } + + body, err := ioutil.ReadAll(rq.Body) + if err != nil { + return nil, NewStatusErr(http.StatusInternalServerError, errors.New("Cannot read request body")) + } + + go func() { + if _, err := client.FinishLaunchRaw(realLaunchID, bytes.NewBuffer(body)); err != nil { + log.Error(err) + } + }() + + return &gorp.MsgRS{Msg: "Launch has been finished"}, nil + }) +} + +func startLaunchHandler(kvStore store.KVStore, client *gorp.Client) http.HandlerFunc { + return JSONHandler(func(rq *http.Request) (interface{}, error) { + uid, err := uuid.NewV4() + if err != nil { + return nil, NewStatusErr(http.StatusInternalServerError, errors.Wrap(errors.New("ok"), "Unable to generate UUID")) + } + + body, err := ioutil.ReadAll(rq.Body) + if err != nil { + return nil, NewStatusErr(http.StatusInternalServerError, errors.New("Cannot read request body")) + } + + go func(b []byte) { + rs, err := client.StartLaunchRaw(bytes.NewBuffer(b)) + if err != nil { + if err := kvStore.Store("pending-launch", uid.String(), b); err != nil { + log.Error(err) + } + } else { + if err := kvStore.Store("uuids", uid.String(), rs.ID); err != nil { + log.Error(err) + } + } + + }(body) + + return &gorp.EntryCreatedRS{ID: uid.String()}, nil + }) +} diff --git a/agent/handlers/http.go b/agent/handlers/http.go new file mode 100644 index 0000000..a71dee3 --- /dev/null +++ b/agent/handlers/http.go @@ -0,0 +1,97 @@ +package handlers + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" +) + +// StatusErr describes HTTP status error +type StatusErr struct { + error + statusCode int +} + +// StackTrace returns stack trace of an error +func (se *StatusErr) StackTrace() errors.StackTrace { + if st, ok := se.error.(stackTracer); ok { + return st.StackTrace() + } + return nil +} + +// NewStatusErr creates new status error +func NewStatusErr(statusCode int, err error) *StatusErr { + return &StatusErr{statusCode: statusCode, error: err} +} + +// HTTPHandlerFunc is a handler func for JSON/REST handlers +type HTTPHandlerFunc func(w http.ResponseWriter, rq *http.Request) error + +// HTTPHandler handles HTTP requests +func HTTPHandler(f HTTPHandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, rq *http.Request) { + w.Header().Add("Content-Type", "application/json; charset=utf-8") + + err := f(w, rq) + if err != nil { + var rs interface{} + + if se, ok := err.(*StatusErr); ok { + w.WriteHeader(se.statusCode) + } + + rs = map[string]string{"error": err.Error()} + if st, ok := err.(stackTracer); ok { + rs.(map[string]string)["stacktrace"] = fmt.Sprintf("%+v", st.StackTrace()) + } + + if wErr := json.NewEncoder(w).Encode(rs); wErr != nil { + log.Error(wErr) + } + } + + } +} + +// RestHandlerFunc handles REST requests +type RestHandlerFunc func(rq *http.Request) (interface{}, error) + +// JSONHandler is a handler for JSON response content type handlers +func JSONHandler(f RestHandlerFunc) http.HandlerFunc { + return func(w http.ResponseWriter, rq *http.Request) { + w.Header().Add("Content-Type", "application/json; charset=utf-8") + + rs, err := f(rq) + if err != nil { + if se, ok := err.(*StatusErr); ok { + w.WriteHeader(se.statusCode) + } + + rs = map[string]string{"error": err.Error()} + if st, ok := err.(stackTracer); ok { + rs.(map[string]string)["stacktrace"] = fmt.Sprintf("%+v", st.StackTrace()) + } + + } else if rs == nil { + rs = map[string]string{} + } + + if wErr := json.NewEncoder(w).Encode(rs); wErr != nil { + log.Error(wErr) + } + } +} + +//ReadJSON reads and unmarshals JSON +func ReadJSON(r io.Reader, s interface{}) error { + return json.NewDecoder(r).Decode(s) +} + +type stackTracer interface { + StackTrace() errors.StackTrace +} diff --git a/agent/handlers/launch.go b/agent/handlers/launch.go new file mode 100644 index 0000000..d6c5041 --- /dev/null +++ b/agent/handlers/launch.go @@ -0,0 +1,30 @@ +package handlers + +// TODO to be determined +//type LaunchHandler interface { +// HandleStart(rq *gorp.StartLaunchRQ) (*gorp.EntryCreatedRS, error) +// HandleFinish(rq *gorp.FinishExecutionRQ) (*gorp.FinishExecutionRQ, error) +//} +// +//type HTTPLaunchHandler struct { +// handler LaunchHandler +//} +// +//func (h *HTTPLaunchHandler) HandleStart(rq *http.Request) (interface{}, error) { +// var body gorp.StartLaunchRQ +// +// if err := ReadJSON(rq.Body, &body); err != nil { +// return nil, err +// } +// +// return h.handler.HandleStart(&body) +//} +//func (h *HTTPLaunchHandler) HandleFinish(rq *http.Request) (interface{}, error) { +// var body gorp.FinishExecutionRQ +// +// if err := ReadJSON(rq.Body, &body); err != nil { +// return nil, err +// } +// +// return h.handler.HandleFinish(&body) +//} diff --git a/agent/main.go b/agent/main.go new file mode 100644 index 0000000..22538ae --- /dev/null +++ b/agent/main.go @@ -0,0 +1,66 @@ +package main + +import ( + "context" + "fmt" + "net/http" + + "github.com/avarabyeu/goRP/agent/handlers" + "github.com/caarlos0/env" + log "github.com/sirupsen/logrus" + "go.uber.org/fx" +) + +type conf struct { + Port int `env:"PORT" envDefault:"9999"` + BasePath string `env:"BASE_PATH" envDefault:"/api/v1"` +} + +func main() { + app := fx.New( + fx.Provide( + newConf, + newMux, + ), + fx.Invoke(initServer), + ) + + app.Run() +} + +func newConf() (*conf, error) { + var cfg conf + if err := env.Parse(&cfg); err != nil { + return nil, err + } + + return &cfg, nil +} + +func newMux(cfg *conf) http.Handler { + // TODO to be done + return handlers.NewMux(cfg.BasePath, nil, nil) +} + +func initServer(lc fx.Lifecycle, handler http.Handler, cfg *conf) { + server := &http.Server{ + Addr: fmt.Sprintf(":%d", cfg.Port), + Handler: handler, + } + lc.Append(fx.Hook{ + OnStart: func(ctx context.Context) error { + log.Infof("Starting HTTP server on port %d", cfg.Port) + + go func() { + if err := server.ListenAndServe(); err != nil { + log.Fatal(err) + } + }() + return nil + }, + OnStop: func(ctx context.Context) error { + log.Info("Stopping HTTP server.") + return server.Shutdown(ctx) + }, + }) +} diff --git a/agent/store/storage.go b/agent/store/storage.go new file mode 100644 index 0000000..4ea715b --- /dev/null +++ b/agent/store/storage.go @@ -0,0 +1,8 @@ +package store + +//KVStore describes CRUD operations over KV store +type KVStore interface { + Store(bucket string, k string, v interface{}) error + Find(bucket string, k string) (interface{}, error) + FindString(bucket, k string) (string, error) +} diff --git a/cli/commands.go b/cli/commands.go index 643a67f..67c8c15 100644 --- a/cli/commands.go +++ b/cli/commands.go @@ -3,11 +3,12 @@ package cli import ( "encoding/json" "fmt" + "net/url" + "os" + "github.com/avarabyeu/goRP/gorp" "github.com/manifoldco/promptui" "gopkg.in/urfave/cli.v1" - "net/url" - "os" ) type config struct { @@ -17,11 +18,10 @@ type config struct { } var ( - //RootCommand is CLI entry point + // RootCommand is CLI entry point RootCommand = []cli.Command{ launchCommand, initCommand, - mergeCommand, } initCommand = cli.Command{ @@ -47,10 +47,14 @@ func initConfiguration(c *cli.Context) error { } } f, err := os.OpenFile(getConfigFile(), os.O_CREATE|os.O_WRONLY, 0600) - if nil != err { + if err != nil { return cli.NewExitError(fmt.Sprintf("Cannot open config file, %s", err), 1) } - defer f.Close() + defer func() { + if closeErr := f.Close(); closeErr != nil { + fmt.Println(closeErr) + } + }() prompt := promptui.Prompt{ Label: "Enter ReportPortal hostname", @@ -85,7 +89,7 @@ func initConfiguration(c *cli.Context) error { Host: host, UUID: uuid, }) - if nil != err { + if err != nil { return cli.NewExitError(fmt.Sprintf("Cannot read config file. %s", err), 1) } @@ -97,25 +101,25 @@ func getConfig(c *cli.Context) (*config, error) { cfg := &config{} if configFilePresent() { f, err := os.Open(getConfigFile()) - if nil != err { + if err != nil { return nil, err } err = json.NewDecoder(f).Decode(cfg) - if nil != err { + if err != nil { return nil, err } } - if v := c.GlobalString("uuid"); "" != v { + if v := c.GlobalString("uuid"); v != "" { cfg.UUID = v } - if v := c.GlobalString("project"); "" != v { + if v := c.GlobalString("project"); v != "" { cfg.Project = v } - if v := c.GlobalString("host"); "" != v { + if v := c.GlobalString("host"); v != "" { cfg.Host = v } - if err := validateConfig(cfg); nil != err { + if err := validateConfig(cfg); err != nil { return nil, err } @@ -124,7 +128,7 @@ func getConfig(c *cli.Context) (*config, error) { func buildClient(ctx *cli.Context) (*gorp.Client, error) { cfg, err := getConfig(ctx) - if nil != err { + if err != nil { return nil, err } return gorp.NewClient(cfg.Host, cfg.Project, cfg.UUID), nil diff --git a/cli/launch.go b/cli/launch.go index 2575ebd..7ed4210 100644 --- a/cli/launch.go +++ b/cli/launch.go @@ -3,17 +3,18 @@ package cli import ( "errors" "fmt" - "github.com/avarabyeu/goRP/gorp" - "gopkg.in/urfave/cli.v1" "strings" "time" + + "github.com/avarabyeu/goRP/gorp" + "gopkg.in/urfave/cli.v1" ) var ( launchCommand = cli.Command{ Name: "launch", Usage: "Operations over launches", - Subcommands: cli.Commands{listLaunchesCommand}, + Subcommands: cli.Commands{listLaunchesCommand, mergeCommand}, } listLaunchesCommand = cli.Command{ @@ -44,6 +45,11 @@ var ( Usage: "Launches Filter", EnvVar: "MERGE_LAUNCH_FILTER", }, + cli.StringFlag{ + Name: "fn, filter-name", + Usage: "Filter Name", + EnvVar: "FILTER_NAME", + }, cli.StringSliceFlag{ Name: "ids", Usage: "Launch IDS to Merge", @@ -67,12 +73,12 @@ var ( func mergeLaunches(c *cli.Context) error { rpClient, err := buildClient(c) - if nil != err { + if err != nil { return err } ids, err := getMergeIDs(c, rpClient) - if nil != err { + if err != nil { return err } rq := &gorp.MergeLaunchesRQ{ @@ -83,8 +89,8 @@ func mergeLaunches(c *cli.Context) error { EndTime: gorp.Timestamp{Time: time.Now().Add(-1 * time.Minute)}, } launchResource, err := rpClient.MergeLaunches(rq) - if nil != err { - return err + if err != nil { + return fmt.Errorf("unable to merge launches: %s", err.Error()) } fmt.Println(launchResource.ID) return nil @@ -92,21 +98,21 @@ func mergeLaunches(c *cli.Context) error { func listLaunches(c *cli.Context) error { rpClient, err := buildClient(c) - if nil != err { + if err != nil { return err } var launches *gorp.LaunchPage - if filters := c.StringSlice("filter"); nil != filters && len(filters) > 0 { + if filters := c.StringSlice("filter"); len(filters) > 0 { filter := strings.Join(filters, "&") launches, err = rpClient.GetLaunchesByFilterString(filter) - } else if filterName := c.String("filter-name"); "" != filterName { + } else if filterName := c.String("filter-name"); filterName != "" { launches, err = rpClient.GetLaunchesByFilterName(filterName) } else { launches, err = rpClient.GetLaunches() } - if nil != err { + if err != nil { return err } @@ -117,20 +123,29 @@ func listLaunches(c *cli.Context) error { } func getMergeIDs(c *cli.Context, rpClient *gorp.Client) ([]string, error) { - if ids := c.StringSlice("ids"); nil != ids && len(ids) > 0 { + if ids := c.StringSlice("ids"); len(ids) > 0 { return ids, nil } + var launches *gorp.LaunchPage + var err error + filter := c.String("filter") - if "" == filter { + filterName := c.String("filter-name") + switch { + case filter != "": + launches, err = rpClient.GetLaunchesByFilterString(filter) + case filterName != "": + launches, err = rpClient.GetLaunchesByFilterName(filterName) + default: return nil, errors.New("no either IDs or filter provided") } - launchesByFilterName, err := rpClient.GetLaunchesByFilterName(filter) - if nil != err { - return nil, err + if err != nil { + return nil, fmt.Errorf("unable to find launches by filter: %s", err.Error()) } - ids := make([]string, len(launchesByFilterName.Content)) - for i, l := range launchesByFilterName.Content { + + ids := make([]string, len(launches.Content)) + for i, l := range launches.Content { ids[i] = l.ID } return ids, nil diff --git a/cli/util.go b/cli/util.go index 7f20577..9bdd29d 100644 --- a/cli/util.go +++ b/cli/util.go @@ -9,15 +9,15 @@ import ( ) func validateConfig(cfg *config) error { - if "" == cfg.UUID { + if cfg.UUID == "" { return errors.New("uuid is not set") } - if "" == cfg.Project { + if cfg.Project == "" { return errors.New("project is not set") } - if "" == cfg.Host { + if cfg.Host == "" { return errors.New("host is not set") } return nil @@ -25,7 +25,7 @@ func validateConfig(cfg *config) error { func answerYes(answer string) bool { lower := strings.ToLower(answer) - return "y" == lower || "yes" == lower + return lower == "y" || lower == "yes" } func configFilePresent() bool { @@ -37,7 +37,7 @@ func getConfigFile() string { return filepath.Join(getHomeDir(), ".gorp") } func getHomeDir() string { - if h := os.Getenv("HOME"); "" != h { + if h := os.Getenv("HOME"); h != "" { return h } curUser, err := user.Current() diff --git a/cli/util_test.go b/cli/util_test.go index 3baf7b3..d95b7cd 100644 --- a/cli/util_test.go +++ b/cli/util_test.go @@ -1,9 +1,10 @@ package cli import ( + "testing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "testing" ) func TestCli(t *testing.T) { diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..b16b682 --- /dev/null +++ b/go.mod @@ -0,0 +1,97 @@ +module github.com/avarabyeu/goRP + +require ( + cloud.google.com/go v0.36.0 // indirect + dmitri.shuralyov.com/app/changes v0.0.0-20181114035150-5af16e21babb // indirect + dmitri.shuralyov.com/service/change v0.0.0-20190203163610-217368fe4577 // indirect + git.apache.org/thrift.git v0.12.0 // indirect + github.com/Shopify/sarama v1.21.0 // indirect + github.com/alecthomas/gometalinter v3.0.0+incompatible // indirect + github.com/caarlos0/env v3.5.0+incompatible + github.com/coreos/go-systemd v0.0.0-20190212144455-93d5ec2c7f76 // indirect + github.com/dustin/go-broadcast v0.0.0-20171205050544-f664265f5a66 // indirect + github.com/gin-contrib/sse v0.0.0-20190226023149-996076df5b33 // indirect + github.com/gin-gonic/gin v1.3.0 // indirect + github.com/gliderlabs/ssh v0.1.3 // indirect + github.com/go-chi/chi v4.0.2+incompatible + github.com/go-logfmt/logfmt v0.4.0 // indirect + github.com/go-playground/locales v0.12.1 // indirect + github.com/go-playground/universal-translator v0.16.0 // indirect + github.com/gofrs/uuid v3.2.0+incompatible + github.com/gogo/protobuf v1.2.1 // indirect + github.com/golang/lint v0.0.0-20181217174547-8f45f776aaf1 // indirect + github.com/golang/protobuf v1.3.0 + github.com/golang/snappy v0.0.1 // indirect + github.com/google/pprof v0.0.0-20190226225141-b51a6544410d // indirect + github.com/googleapis/gax-go v2.0.2+incompatible // indirect + github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e // indirect + github.com/gorilla/mux v1.7.0 // indirect + github.com/gravitational/trace v0.0.0-20190218181455-5d6afe38af2b // indirect + github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc // indirect + github.com/grpc-ecosystem/grpc-gateway v1.7.0 // indirect + github.com/jonboulle/clockwork v0.1.0 // indirect + github.com/kisielk/errcheck v1.2.0 // indirect + github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect + github.com/leodido/go-urn v1.1.0 // indirect + github.com/lunixbochs/vtclean v1.0.0 // indirect + github.com/mailgun/multibuf v0.0.0-20150714184110-565402cd71fb // indirect + github.com/manifoldco/promptui v0.3.2 + github.com/manucorporat/stats v0.0.0-20180402194714-3ba42d56d227 // indirect + github.com/mattn/go-colorable v0.1.1 // indirect + github.com/mattn/go-isatty v0.0.6 // indirect + github.com/microcosm-cc/bluemonday v1.0.2 // indirect + github.com/nicksnyder/go-i18n v1.10.0 // indirect + github.com/onsi/ginkgo v1.7.0 + github.com/onsi/gomega v1.4.3 + github.com/openzipkin/zipkin-go v0.1.5 // indirect + github.com/pelletier/go-toml v1.2.0 // indirect + github.com/pkg/errors v0.8.1 + github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 // indirect + github.com/prometheus/common v0.2.0 + github.com/prometheus/procfs v0.0.0-20190225181712-6ed1f7e10411 // indirect + github.com/russross/blackfriday v2.0.0+incompatible // indirect + github.com/shurcooL/go v0.0.0-20190121191506-3fef8c783dec // indirect + github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d // indirect + github.com/shurcooL/highlight_diff v0.0.0-20181222201841-111da2e7d480 // indirect + github.com/shurcooL/highlight_go v0.0.0-20181215221002-9d8641ddf2e1 // indirect + github.com/shurcooL/home v0.0.0-20190204141146-5c8ae21d4240 // indirect + github.com/shurcooL/htmlg v0.0.0-20190120222857-1e8a37b806f3 // indirect + github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414 // indirect + github.com/shurcooL/issues v0.0.0-20190120000219-08d8dadf8acb // indirect + github.com/shurcooL/issuesapp v0.0.0-20181229001453-b8198a402c58 // indirect + github.com/shurcooL/notifications v0.0.0-20181111060504-bcc2b3082a7a // indirect + github.com/shurcooL/octicon v0.0.0-20181222203144-9ff1a4cf27f4 // indirect + github.com/shurcooL/reactions v0.0.0-20181222204718-145cd5e7f3d1 // indirect + github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect + github.com/shurcooL/webdavfs v0.0.0-20181215192745-5988b2d638f6 // indirect + github.com/sirupsen/logrus v1.3.0 + github.com/stretchr/testify v1.3.0 // indirect + github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 // indirect + github.com/vulcand/oxy v0.0.0-20181130145254-c34b0c501e43 // indirect + github.com/vulcand/predicate v1.1.0 // indirect + go.opencensus.io v0.19.0 // indirect + go.uber.org/atomic v1.3.2 // indirect + go.uber.org/dig v1.7.0 // indirect + go.uber.org/fx v1.9.0 + go.uber.org/goleak v0.10.0 // indirect + go.uber.org/multierr v1.1.0 // indirect + go4.org v0.0.0-20190218023631-ce4c26f7be8e // indirect + golang.org/x/build v0.0.0-20190226180436-80ca8d25ddd4 // indirect + golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b // indirect + golang.org/x/exp v0.0.0-20190221220918-438050ddec5e // indirect + golang.org/x/net v0.0.0-20190226215741-afe646ca25a4 // indirect + golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421 // indirect + golang.org/x/perf v0.0.0-20190124201629-844a5f5b46f4 // indirect + golang.org/x/sys v0.0.0-20190226215855-775f8194d0f9 // indirect + golang.org/x/tools v0.0.0-20190226205152-f727befe758c // indirect + google.golang.org/genproto v0.0.0-20190226184841-fc2db5cae922 // indirect + google.golang.org/grpc v1.19.0 // indirect + gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c // indirect + gopkg.in/go-playground/validator.v8 v8.18.2 // indirect + gopkg.in/go-playground/validator.v9 v9.27.0 // indirect + gopkg.in/reportportal/commons-go.v5 v5.0.3 + gopkg.in/resty.v1 v1.11.0 + gopkg.in/urfave/cli.v1 v1.20.0 + honnef.co/go/tools v0.0.0-20190215041234-466a0476246c // indirect + sourcegraph.com/sqs/pbtypes v1.0.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..273a63f --- /dev/null +++ b/go.sum @@ -0,0 +1,406 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.33.1/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.36.0/go.mod h1:RUoy9p/M4ge0HzT8L+SDZ8jg+Q6fth0CiBuhFJpSV40= +dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/app/changes v0.0.0-20181114035150-5af16e21babb/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= +dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU= +dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/service/change v0.0.0-20190203163610-217368fe4577/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4= +dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU= +git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +git.apache.org/thrift.git v0.0.0-20181218151757-9b75e4fe745a/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +git.apache.org/thrift.git v0.12.0/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/DataDog/zstd v1.3.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/sarama v1.21.0/go.mod h1:yuqtN/pe8cXRWG5zPaO7hCfNJp5MwmkoJEoLjkm5tCQ= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/alecthomas/gometalinter v2.0.11+incompatible/go.mod h1:qfIpQGGz3d+NmgyPBqv+LSh50emm1pt72EtcX2vKYQk= +github.com/alecthomas/gometalinter v2.0.12+incompatible h1:RBUbc8pKtqRoVCymENDl7cpWS9Ht5XNnwwk0cKjpteI= +github.com/alecthomas/gometalinter v2.0.12+incompatible/go.mod h1:qfIpQGGz3d+NmgyPBqv+LSh50emm1pt72EtcX2vKYQk= +github.com/alecthomas/gometalinter v3.0.0+incompatible/go.mod h1:qfIpQGGz3d+NmgyPBqv+LSh50emm1pt72EtcX2vKYQk= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= +github.com/caarlos0/env v3.5.0+incompatible h1:Yy0UN8o9Wtr/jGHZDpCBLpNrzcFLLM2yixi/rBrKyJs= +github.com/caarlos0/env v3.5.0+incompatible/go.mod h1:tdCsowwCzMLdkqRYDlHpZCp2UooDD3MspDBjZ2AD02Y= +github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190212144455-93d5ec2c7f76/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-broadcast v0.0.0-20171205050544-f664265f5a66 h1:QnnoVdChKs+GeTvN4rPYTW6b5U6M3HMEvQ/+x4IGtfY= +github.com/dustin/go-broadcast v0.0.0-20171205050544-f664265f5a66/go.mod h1:kTEh6M2J/mh7nsskr28alwLCXm/DSG5OSA/o31yy2XU= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.0.0-20190226023149-996076df5b33 h1:0KW+RBLmpRfNdJOo/l4MUpMt5G2v5+U2y2jfaQ2DyrI= +github.com/gin-contrib/sse v0.0.0-20190226023149-996076df5b33/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s= +github.com/gin-gonic/gin v1.3.0 h1:kCmZyPklC0gVdL728E6Aj20uYBJV93nj/TkwBTKhFbs= +github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y= +github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/gliderlabs/ssh v0.1.3/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-chi/chi v3.3.4+incompatible h1:X+OApYAmoQS6jr1WoUgW+t5Ry5RYGXq2A//WAL5xdAU= +github.com/go-chi/chi v3.3.4+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-chi/chi v4.0.1+incompatible h1:RSRC5qmFPtO90t7pTL0DBMNpZFsb/sHF3RXVlDgFisA= +github.com/go-chi/chi v4.0.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-chi/chi v4.0.2+incompatible h1:maB6vn6FqCxrpz4FqWdh4+lwpyZIQS7YEAUcHlgXVRs= +github.com/go-chi/chi v4.0.2+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc= +github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM= +github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM= +github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3 h1:I4BOK3PBMjhWfQM2zPJKK7lOBGsrsvOB7kBELP33hiE= +github.com/golang/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.0 h1:kbxbvI4Un1LUWKxufD+BiE6AEExYYgkQLQmLFqA1LFk= +github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190226225141-b51a6544410d/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= +github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= +github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= +github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gordonklaus/ineffassign v0.0.0-20180909121442-1003c8bd00dc h1:cJlkeAx1QYgO5N80aF5xRGstVsRQwgLR7uA2FnP1ZjY= +github.com/gordonklaus/ineffassign v0.0.0-20180909121442-1003c8bd00dc/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gravitational/trace v0.0.0-20180717152918-4a5e142f3251 h1:wvLRc9hG1+3qE4rVa/qAkcgxcdznlyo9DyAahNo9AUs= +github.com/gravitational/trace v0.0.0-20180717152918-4a5e142f3251/go.mod h1:RvdOUHE4SHqR3oXlFFKnGzms8a5dugHygGw1bqDstYI= +github.com/gravitational/trace v0.0.0-20190218181455-5d6afe38af2b/go.mod h1:RvdOUHE4SHqR3oXlFFKnGzms8a5dugHygGw1bqDstYI= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/gregjones/httpcache v0.0.0-20190212212710-3befbb6ad0cc/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= +github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.6.2/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/grpc-ecosystem/grpc-gateway v1.7.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU= +github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8= +github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw= +github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw= +github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= +github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= +github.com/mailgun/multibuf v0.0.0-20150714184110-565402cd71fb h1:m2FGM8K2LC9Zyt/7zbQNn5Uvf/YV7vFWKtoMcC7hHU8= +github.com/mailgun/multibuf v0.0.0-20150714184110-565402cd71fb/go.mod h1:E0vRBBIQUHcRtmL/oR6w/jehh4FJqJFxe86gBnw9gXc= +github.com/manifoldco/promptui v0.3.2 h1:rir7oByTERac6jhpHUPErHuopoRDvO3jxS+FdadEns8= +github.com/manifoldco/promptui v0.3.2/go.mod h1:8JU+igZ+eeiiRku4T5BjtKh2ms8sziGpSYl1gN8Bazw= +github.com/manucorporat/stats v0.0.0-20180402194714-3ba42d56d227 h1:KIaAZ/V+/0/6BOULrmBQ9T1ed8BkKqGIjIKW923nJuo= +github.com/manucorporat/stats v0.0.0-20180402194714-3ba42d56d227/go.mod h1:ruMr5t05gVho4tuDv0PbI0Bb8nOxc/5Y6JzRHe/yfA0= +github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.6 h1:SrwhHcpV4nWrMGdNcC2kXpMfcBVYGDuTArqyhocJgvA= +github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= +github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= +github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= +github.com/nicksnyder/go-i18n v1.10.0 h1:5AzlPKvXBH4qBzmZ09Ua9Gipyruv6uApMcrNZdo96+Q= +github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= +github.com/openzipkin/zipkin-go v0.1.5/go.mod h1:8NDCjKHoHW1XOp/vf3lClHem0b91r4433B67KXyKXAQ= +github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.0.0-20181218105931-67670fe90761/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= +github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190225181712-6ed1f7e10411/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/russross/blackfriday v2.0.0+incompatible/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= +github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= +github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= +github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go v0.0.0-20190121191506-3fef8c783dec/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= +github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw= +github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI= +github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_diff v0.0.0-20181222201841-111da2e7d480/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU= +github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/highlight_go v0.0.0-20181215221002-9d8641ddf2e1/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag= +github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/home v0.0.0-20190204141146-5c8ae21d4240/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg= +github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/htmlg v0.0.0-20190120222857-1e8a37b806f3/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw= +github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y= +github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg= +github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q= +github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issues v0.0.0-20190120000219-08d8dadf8acb/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ= +github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/issuesapp v0.0.0-20181229001453-b8198a402c58/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I= +github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/notifications v0.0.0-20181111060504-bcc2b3082a7a/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0= +github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/octicon v0.0.0-20181222203144-9ff1a4cf27f4/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ= +github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/reactions v0.0.0-20181222204718-145cd5e7f3d1/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk= +github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4= +github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= +github.com/shurcooL/webdavfs v0.0.0-20181215192745-5988b2d638f6/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME= +github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE= +github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= +github.com/tsenart/deadcode v0.0.0-20160724212837-210d2dc333e9 h1:vY5WqiEon0ZSTGM3ayVVi+twaHKHDFUVloaQ/wug9/c= +github.com/tsenart/deadcode v0.0.0-20160724212837-210d2dc333e9/go.mod h1:q+QjxYvZ+fpjMXqs+XEriussHjSYqeXVnAdSV1tkMYk= +github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= +github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 h1:BasDe+IErOQKrMVXab7UayvSlIpiyGwRvuX3EKYY7UA= +github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= +github.com/vulcand/oxy v0.0.0-20181130145254-c34b0c501e43 h1:2+LBGeYYE8JgE1UCKx+qRpoFyvF4NdGQpR8bFCCPfEw= +github.com/vulcand/oxy v0.0.0-20181130145254-c34b0c501e43/go.mod h1:giFb8dicROVdV5W0HXlA5siMBLWKnVXZlkA4Y5ZIzrY= +github.com/vulcand/predicate v1.1.0 h1:Gq/uWopa4rx/tnZu2opOSBqHK63Yqlou/SzrbwdJiNg= +github.com/vulcand/predicate v1.1.0/go.mod h1:mlccC5IRBoc2cIFmCB8ZM62I3VDb6p2GXESMHa3CnZg= +go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= +go.opencensus.io v0.19.0/go.mod h1:AYeH0+ZxYyghG8diqaaIq/9P3VgCCt5GF2ldCY4dkFg= +go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/dig v1.7.0 h1:E5/L92iQTNJTjfgJF2KgU+/JpMaiuvK2DHLBj0+kSZk= +go.uber.org/dig v1.7.0/go.mod h1:z+dSd2TP9Usi48jL8M3v63iSBVkiwtVyMKxMZYYauPg= +go.uber.org/fx v1.8.0 h1:/VYBPRh/ZWLG4oNgVPIJeqHAlar4hE8olnhk4dTNZbg= +go.uber.org/fx v1.8.0/go.mod h1:mFdUyAUuJ3w4jAckiKSKbldsxy1ojpAMJ+dVZg5Y0Aw= +go.uber.org/fx v1.9.0 h1:7OAz8ucp35AU8eydejpYG7QrbE8rLKzGhHbZlJi5LYY= +go.uber.org/fx v1.9.0/go.mod h1:mFdUyAUuJ3w4jAckiKSKbldsxy1ojpAMJ+dVZg5Y0Aw= +go.uber.org/goleak v0.10.0 h1:G3eWbSNIskeRqtsN/1uI5B+eP73y3JUuBsv9AZjehb4= +go.uber.org/goleak v0.10.0/go.mod h1:VCZuO8V8mFPlL0F5J5GK1rtHV3DrFcQ1R8ryq7FK0aI= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +go4.org v0.0.0-20190218023631-ce4c26f7be8e/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= +golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +golang.org/x/build v0.0.0-20190226180436-80ca8d25ddd4/go.mod h1:LS5++pZInCkeGSsPGP/1yB0yvU9gfqv2yD1PQgIbDYI= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc h1:F5tKCVGp+MUAHhKp5MZtGqAlGX3+oCsiL1Q629FL90M= +golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664 h1:YbZJ76lQ1BqNhVe7dKTSB67wDrc2VPRR75IyGyyPDX8= +golang.org/x/crypto v0.0.0-20190130090550-b01c7a725664/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b h1:+/WWzjwW6gidDJnMKWLKLX1gxn7irUTF1fLpQovfQ5M= +golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190221220918-438050ddec5e/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3 h1:x/bBzNauLQAlE3fLku/xy92Y8QwKX5HZymrMz2IiKFc= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20181217174547-8f45f776aaf1/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181217023233-e147a9138326/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e h1:bRhVy7zSSasaqNksaRZiA5EEI+Ei4I1nO5Jh72wfHlg= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3 h1:ulvT7fqt0yHWzpJwI57MezWnYDVpCAYBVuYst/L+fAY= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190226215741-afe646ca25a4 h1:v9iNk7wDkdbc0AEntnZ+bru4iRMZ4+vI3W1knqDZijs= +golang.org/x/net v0.0.0-20190226215741-afe646ca25a4/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181120190819-8f65e3013eba/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +golang.org/x/perf v0.0.0-20190124201629-844a5f5b46f4/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181218192612-074acd46bca6/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190108104531-7fbe1cd0fcc2 h1:ku9Kvp2ZBWAz3GyvuUH3UV1bZCd7RxH0Qf1epWfIDKc= +golang.org/x/sys v0.0.0-20190108104531-7fbe1cd0fcc2/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564 h1:o6ENHFwwr1TZ9CUPQcfo1HGvLP1OPsPOTB7xCIOPNmU= +golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190226215855-775f8194d0f9 h1:N26gncmS+iqc/W/SKhX3ElI5pkt72XYoRLgi5Z70LSc= +golang.org/x/sys v0.0.0-20190226215855-775f8194d0f9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181122213734-04b5d21e00f1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181219222714-6e267b5cc78e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190108222858-421f03a57a64 h1:9Y3iftuqayHi0EqSzJ3MrPoNIHHcIvicTPdfepyP5tE= +golang.org/x/tools v0.0.0-20190108222858-421f03a57a64/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190130214255-bb1329dc71a0/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.0.0-20181220000619-583d854617af/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= +google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20181109154231-b5d43981345b/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20181219182458-5a97ab628bfb/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg= +google.golang.org/genproto v0.0.0-20190201180003-4b09977fb922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= +google.golang.org/genproto v0.0.0-20190226184841-fc2db5cae922/go.mod h1:L3J43x8/uS+qIUoksaLKe6OS3nUKxOKuIFz1sl2/jx4= +google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= +google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c h1:vTxShRUnK60yd8DZU+f95p1zSLj814+5CuEh7NjF2/Y= +gopkg.in/alecthomas/kingpin.v3-unstable v3.0.0-20180810215634-df19058c872c/go.mod h1:3HH7i1SgMqlzxCcBmUHW657sD4Kvv9sC3HpL3YukzwA= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/go-playground/validator.v8 v8.18.2 h1:lFB4DoMU6B626w8ny76MV7VX6W2VHct2GVOI3xgiMrQ= +gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= +gopkg.in/go-playground/validator.v9 v9.26.0 h1:2NPPsBpD0ZoxshmLWewQru8rWmbT5JqSzz9D1ZrAjYQ= +gopkg.in/go-playground/validator.v9 v9.26.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/go-playground/validator.v9 v9.27.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/reportportal/commons-go.v5 v5.0.3 h1:PGOpfxrvj4hZfzLyXJ+urFa1Rxbv+jtJ7cdMMN3GI5U= +gopkg.in/reportportal/commons-go.v5 v5.0.3/go.mod h1:yWSspZaritPJQ0LCz+1qqR/wyhw64jBTKYwXtsQJI+I= +gopkg.in/resty.v1 v1.11.0 h1:z5nqGs/W/h91PLOc+WZefPj8rRZe8Ctlgxg/AtbJ+NE= +gopkg.in/resty.v1 v1.11.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0= +gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190215041234-466a0476246c/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck= +sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= +sourcegraph.com/sqs/pbtypes v1.0.0/go.mod h1:3AciMUv4qUuRHRHhOG4TZOB+72GdPVz5k+c648qsFS4= diff --git a/gorp/client.go b/gorp/client.go index 1a9fb1c..090f8b8 100644 --- a/gorp/client.go +++ b/gorp/client.go @@ -1,9 +1,11 @@ package gorp import ( + "bytes" "fmt" - "gopkg.in/resty.v1" "time" + + "gopkg.in/resty.v1" ) //Client is ReportPortal REST API Client @@ -35,10 +37,20 @@ func NewClient(host, project, uuid string) *Client { //StartLaunch starts new launch in RP func (c *Client) StartLaunch(launch *StartLaunchRQ) (*EntryCreatedRS, error) { + return c.startLaunch(launch) +} + +//StartLaunchRaw starts new launch in RP with body in form of bytes buffer +func (c *Client) StartLaunchRaw(body *bytes.Buffer) (*EntryCreatedRS, error) { + return c.startLaunch(body) +} + +//StartLaunch starts new launch in RP +func (c *Client) startLaunch(body interface{}) (*EntryCreatedRS, error) { var rs EntryCreatedRS _, err := c.http.R(). SetPathParams(map[string]string{"project": c.project}). - SetBody(launch). + SetBody(body). SetResult(&rs). Post("/api/v1/{project}/launch") return &rs, err @@ -46,13 +58,23 @@ func (c *Client) StartLaunch(launch *StartLaunchRQ) (*EntryCreatedRS, error) { //FinishLaunch finishes launch in RP func (c *Client) FinishLaunch(id string, launch *FinishExecutionRQ) (*MsgRS, error) { + return c.finishLaunch(id, launch) +} + +//FinishLaunchRaw finishes launch in RP with body in form of bytes buffer +func (c *Client) FinishLaunchRaw(id string, body *bytes.Buffer) (*MsgRS, error) { + return c.finishLaunch(id, body) +} + +//FinishLaunch finishes launch in RP +func (c *Client) finishLaunch(id string, body interface{}) (*MsgRS, error) { var rs MsgRS _, err := c.http.R(). SetPathParams(map[string]string{ "project": c.project, "launchId": id, }). - SetBody(launch). + SetBody(body). SetResult(&rs). Put("/api/v1/{project}/launch/{launchId}/finish") return &rs, err @@ -77,38 +99,68 @@ func (c *Client) StopLaunch(id string) (*MsgRS, error) { //StartTest starts new test in RP func (c *Client) StartTest(item *StartTestRQ) (*EntryCreatedRS, error) { + return c.startTest(item) +} + +//StartTestRaw starts new test in RP accepting request body as array of bytes +func (c *Client) StartTestRaw(body *bytes.Buffer) (*EntryCreatedRS, error) { + return c.startTest(body) +} + +//startTest starts new test in RP +func (c *Client) startTest(body interface{}) (*EntryCreatedRS, error) { var rs EntryCreatedRS _, err := c.http.R(). SetPathParams(map[string]string{"project": c.project}). - SetBody(item). + SetBody(body). SetResult(&rs). Post("/api/v1/{project}/item/") return &rs, err } -//StartChildTest starts new test in RP -func (c *Client) StartChildTest(parent string, item *StartTestRQ) (*EntryCreatedRS, error) { +//startChildTest starts new test in RP +func (c *Client) startChildTest(parent string, body interface{}) (*EntryCreatedRS, error) { var rs EntryCreatedRS _, err := c.http.R(). SetPathParams(map[string]string{ "project": c.project, "itemId": parent, }). - SetBody(item). + SetBody(body). SetResult(&rs). Post("/api/v1/{project}/item/{itemId}") return &rs, err } +//StartChildTest starts new test in RP +func (c *Client) StartChildTest(parent string, item *StartTestRQ) (*EntryCreatedRS, error) { + return c.startChildTest(parent, item) +} + +//StartChildTestRaw starts new test in RP accepting request body as array of bytes +func (c *Client) StartChildTestRaw(parent string, body *bytes.Buffer) (*EntryCreatedRS, error) { + return c.startChildTest(parent, body) +} + //FinishTest finishes test in RP func (c *Client) FinishTest(id string, launch *FinishTestRQ) (*MsgRS, error) { + return c.finishTest(id, launch) +} + +//FinishTestRaw finishes test in RP accepting body as array of bytes +func (c *Client) FinishTestRaw(id string, body *bytes.Buffer) (*MsgRS, error) { + return c.finishTest(id, body) +} + +//finishTest finishes test in RP +func (c *Client) finishTest(id string, body interface{}) (*MsgRS, error) { var rs MsgRS _, err := c.http.R(). SetPathParams(map[string]string{ "project": c.project, "itemId": id, }). - SetBody(launch). + SetBody(body). SetResult(&rs). Put("/api/v1/{project}/item/{itemId}") return &rs, err @@ -162,11 +214,11 @@ func (c *Client) GetLaunchesByFilterString(filter string) (*LaunchPage, error) { //GetLaunchesByFilterName retrieves launches by filter name func (c *Client) GetLaunchesByFilterName(name string) (*LaunchPage, error) { filter, err := c.GetFiltersByName(name) - if nil != err { + if err != nil { return nil, err } - if filter.Page.Size < 1 { + if filter.Page.Size < 1 || len(filter.Content) == 0 { return nil, fmt.Errorf("no filter %s found", name) } diff --git a/gorp/client_test.go b/gorp/client_test.go index 4f073ff..d3246a3 100644 --- a/gorp/client_test.go +++ b/gorp/client_test.go @@ -1,10 +1,11 @@ package gorp import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" "net/http" "net/http/httptest" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) var _ = Describe("ReportPortal Client", func() { diff --git a/gorp/gorp_suite_test.go b/gorp/gorp_suite_test.go index 2dcc561..fdc8543 100644 --- a/gorp/gorp_suite_test.go +++ b/gorp/gorp_suite_test.go @@ -1,9 +1,10 @@ package gorp_test import ( + "testing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "testing" ) func TestGorp(t *testing.T) { diff --git a/gorp/model.go b/gorp/model.go index 922f202..bc90ca7 100644 --- a/gorp/model.go +++ b/gorp/model.go @@ -6,6 +6,8 @@ import ( "time" ) +const defaultDateTimeFormat = "2006-01-02T15:04:05.999-0700" + type ( //LaunchMode - DEFAULT/DEBUG LaunchMode string @@ -94,12 +96,6 @@ type ( } `json:"defects,omitempty"` } - //Timestamp is a wrapper around Time to support - //Epoch milliseconds - Timestamp struct { - time.Time - } - //MergeType is type of merge: BASIC or DEEP MergeType string @@ -127,6 +123,7 @@ type ( //StartLaunchRQ payload representation StartLaunchRQ struct { StartRQ + Mode string `json:"mode"` } //FinishTestRQ payload representation @@ -174,13 +171,25 @@ type ( MsgRS struct { Msg string `json:"msg,omitempty"` } + + //Timestamp is a wrapper around Time to support + //Epoch milliseconds + Timestamp struct { + time.Time + } ) //UnmarshalJSON converts Epoch milliseconds (timestamp) to appropriate object -func (rt *Timestamp) UnmarshalJSON(b []byte) (err error) { - msInt, err := strconv.ParseInt(strings.Trim(string(b), "\""), 10, 64) +func (rt *Timestamp) UnmarshalJSON(b []byte) error { + trimmed := strings.Trim(string(b), "\"") + msInt, err := strconv.ParseInt(trimmed, 10, 64) if err != nil { - return err + dt, err := time.Parse(defaultDateTimeFormat, trimmed) + if err != nil { + return err + } + rt.Time = dt + return nil } rt.Time = time.Unix(0, msInt*int64(time.Millisecond)) diff --git a/gorp/model_test.go b/gorp/model_test.go index cc862c9..f874c90 100644 --- a/gorp/model_test.go +++ b/gorp/model_test.go @@ -2,9 +2,10 @@ package gorp import ( "encoding/json" + "time" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "time" ) var _ = Describe("UnixTime", func() { diff --git a/gorp/util.go b/gorp/util.go index cf03ca3..03598eb 100644 --- a/gorp/util.go +++ b/gorp/util.go @@ -12,11 +12,11 @@ func ConvertToFilterParams(filter *FilterResource) map[string]string { params[fmt.Sprintf("filter.%s.%s", f.Condition, f.Field)] = f.Value } - if nil != filter.SelectionParams { - if 0 != filter.SelectionParams.PageNumber { + if filter.SelectionParams != nil { + if filter.SelectionParams.PageNumber != 0 { params["page.page"] = strconv.Itoa(filter.SelectionParams.PageNumber) } - if nil != filter.SelectionParams.Orders { + if filter.SelectionParams.Orders != nil { for _, order := range filter.SelectionParams.Orders { params["page.sort"] = fmt.Sprintf("%s,%s", order.SortingColumn, directionToStr(order.Asc)) } diff --git a/main.go b/main.go index f4e8661..792e7e1 100644 --- a/main.go +++ b/main.go @@ -14,6 +14,9 @@ var ( ) func main() { + log.SetFlags(0) + log.SetOutput(os.Stdout) + app := cli.NewApp() app.Name = "goRP" app.Usage = "ReportPortal CLI Client" @@ -39,9 +42,15 @@ func main() { } app.Commands = rp.RootCommand + defer func() { + if r := recover(); r != nil { + log.Fatalf("error: %v", r) + } + }() err := app.Run(os.Args) - if nil != err { - log.Fatal(err) + if err != nil { + //nolint:gocritic + log.Fatal(err.Error()) } } diff --git a/util/util.go b/util/util.go new file mode 100644 index 0000000..03a4537 --- /dev/null +++ b/util/util.go @@ -0,0 +1,25 @@ +package util + +import ( + "fmt" + "time" + + log "github.com/sirupsen/logrus" +) + +//Retry executes callback func until it executes successfully +func Retry(attempts int, timeout time.Duration, callback func() (interface{}, error)) (interface{}, error) { + var err error + for i := 0; i < attempts; i++ { + var res interface{} + res, err = callback() + if err == nil { + return res, nil + } + log.Warnf("Retry failed with the following error: %s", err) + + <-time.After(timeout) + log.Infof("Retrying... Attempt: %d. Left: %d", i+1, attempts-1-i) + } + return nil, fmt.Errorf("after %d attempts, last error: %s", attempts, err) +}