diff --git a/.github/workflows/go-tests.yml b/.github/workflows/go-tests.yml index 148c60de..17244a75 100644 --- a/.github/workflows/go-tests.yml +++ b/.github/workflows/go-tests.yml @@ -30,10 +30,8 @@ jobs: with: go-version: 'stable' - uses: actions/checkout@v3 - - uses: golangci/golangci-lint-action@v3 - with: - skip-cache: true - args: --timeout=8m --build-tags testing + - name: make lint + run: make golangci-lint && GOLANGCI_LINT_EXTRA_ARGS="--timeout=8m --build-tags testing" make lint - name: Verify go vendor, go modules and gofmt run: | sudo apt-get install -y jq diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000..e9004a23 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: MIT +linters: + disable-all: true + fast: false + enable: + - gci + - goconst + - gocritic + - gocyclo + - gofmt + - gofumpt + - goimports + - godox + - govet + - gosec + - gosimple + - importas + - ineffassign + - loggercheck + - misspell + - nakedret + - nilerr + - predeclared + - promlinter + - revive + - staticcheck + - unconvert + - unused + - wastedassign + - whitespace + +linters-settings: + gci: + sections: + - standard + - default + - prefix(github.com/cloudbase/garm) + + goimports: + local-prefixes: github.com/cloudbase/garm diff --git a/Makefile b/Makefile index 74c09dc0..3914e9be 100644 --- a/Makefile +++ b/Makefile @@ -10,47 +10,49 @@ VERSION ?= $(shell git describe --tags --match='v[0-9]*' --dirty --always) GARM_REF ?= $(shell git rev-parse --abbrev-ref HEAD) GO ?= go +.PHONY: help +help: ## Display this help. + @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) + default: build +##@ Build + .PHONY : build-static test install-lint-deps lint go-test fmt fmtcheck verify-vendor verify create-release-files release -build-static: +build-static: ## Build garm statically @echo Building garm docker build --tag $(IMAGE_TAG) -f Dockerfile.build-static . docker run --rm -e USER_ID=$(USER_ID) -e GARM_REF=$(GARM_REF) -e USER_GROUP=$(USER_GROUP) -v $(PWD)/build:/build/output:z $(IMAGE_TAG) /build-static.sh @echo Binaries are available in $(PWD)/build -create-release-files: - ./scripts/make-release.sh - -release: build-static create-release-files - -clean: +clean: ## Clean up build artifacts @rm -rf ./bin ./build ./release -build: +.PHONY: build +build: ## Build garm @echo Building garm ${VERSION} $(shell mkdir -p ./bin) @$(GO) build -ldflags "-s -w -X main.Version=${VERSION}" -tags osusergo,netgo,sqlite_omit_load_extension -o bin/garm ./cmd/garm @$(GO) build -ldflags "-s -w -X github.com/cloudbase/garm/cmd/garm-cli/cmd.Version=${VERSION}" -tags osusergo,netgo,sqlite_omit_load_extension -o bin/garm-cli ./cmd/garm-cli @echo Binaries are available in $(PWD)/bin -test: verify go-test +test: verify go-test ## Run tests -install-lint-deps: - @$(GO) install github.com/golangci/golangci-lint/cmd/golangci-lint@latest +##@ Release +create-release-files: + ./scripts/make-release.sh -lint: - @golangci-lint run --timeout=8m --build-tags testing +release: build-static create-release-files ## Create a release -go-test: - @$(GO) test -race -mod=vendor -tags testing -v $(TEST_ARGS) -timeout=15m -parallel=4 -count=1 ./... +##@ Lint / Verify +.PHONY: lint +lint: golangci-lint $(GOLANGCI_LINT) ## Run linting. + $(GOLANGCI_LINT) run -v --build-tags testing $(GOLANGCI_LINT_EXTRA_ARGS) -fmt: - @$(GO) fmt $$(go list ./...) - -fmtcheck: - @gofmt -l -s $$(go list ./... | sed 's|github.com/cloudbase/garm/||g') | grep ".*\.go"; if [ "$$?" -eq 0 ]; then echo "gofmt check failed; please run gofmt -w -s"; exit 1;fi +.PHONY: lint-fix +lint-fix: golangci-lint $(GOLANGCI_LINT) ## Lint the codebase and run auto-fixers if supported by the linte + GOLANGCI_LINT_EXTRA_ARGS=--fix $(MAKE) lint verify-vendor: ## verify if all the go.mod/go.sum files are up-to-date $(eval TMPDIR := $(shell mktemp -d)) @@ -59,4 +61,32 @@ verify-vendor: ## verify if all the go.mod/go.sum files are up-to-date @diff -r -u -q ${ROOTDIR} ${TMPDIR}/garm >/dev/null 2>&1; if [ "$$?" -ne 0 ];then echo "please run: go mod tidy && go mod vendor"; exit 1; fi @rm -rf ${TMPDIR} -verify: verify-vendor lint fmtcheck +verify: verify-vendor lint fmtcheck ## Run all verify-* targets + +##@ Development + +go-test: ## Run tests + @$(GO) test -race -mod=vendor -tags testing -v $(TEST_ARGS) -timeout=15m -parallel=4 -count=1 ./... + +fmt: ## Run go fmt against code. + @$(GO) fmt $$(go list ./...) + + +##@ Build Dependencies + +## Location to install dependencies to +LOCALBIN ?= $(shell pwd)/bin +$(LOCALBIN): + mkdir -p $(LOCALBIN) + +## Tool Binaries +GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint + +## Tool Versions +GOLANGCI_LINT_VERSION ?= v1.56.2 + +.PHONY: golangci-lint +golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. If wrong version is installed, it will be overwritten. +$(GOLANGCI_LINT): $(LOCALBIN) + test -s $(LOCALBIN)/golangci-lint && $(LOCALBIN)/golangci-lint --version | grep -q $(GOLANGCI_LINT_VERSION) || \ + GOBIN=$(LOCALBIN) go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_VERSION) diff --git a/apiserver/controllers/controllers.go b/apiserver/controllers/controllers.go index 7c33695e..256d8efc 100644 --- a/apiserver/controllers/controllers.go +++ b/apiserver/controllers/controllers.go @@ -22,18 +22,18 @@ import ( "net/http" "strings" + "github.com/gorilla/mux" + "github.com/gorilla/websocket" + "github.com/pkg/errors" + gErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm-provider-common/util" "github.com/cloudbase/garm/apiserver/params" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/metrics" runnerParams "github.com/cloudbase/garm/params" - "github.com/cloudbase/garm/runner" + "github.com/cloudbase/garm/runner" //nolint:typecheck wsWriter "github.com/cloudbase/garm/websocket" - - "github.com/gorilla/mux" - "github.com/gorilla/websocket" - "github.com/pkg/errors" ) func NewAPIController(r *runner.Runner, authenticator *auth.Authenticator, hub *wsWriter.Hub) (*APIController, error) { @@ -107,19 +107,21 @@ func (a *APIController) handleWorkflowJobEvent(ctx context.Context, w http.Respo hookType := r.Header.Get("X-Github-Hook-Installation-Target-Type") if err := a.r.DispatchWorkflowJob(hookType, signature, body); err != nil { - if errors.Is(err, gErrors.ErrNotFound) { + switch { + case errors.Is(err, gErrors.ErrNotFound): metrics.WebhooksReceived.WithLabelValues( "false", // label: valid "owner_unknown", // label: reason ).Inc() slog.With(slog.Any("error", err)).ErrorContext(ctx, "got not found error from DispatchWorkflowJob. webhook not meant for us?") return - } else if strings.Contains(err.Error(), "signature") { // TODO: check error type + case strings.Contains(err.Error(), "signature"): + // nolint:golangci-lint,godox TODO: check error type metrics.WebhooksReceived.WithLabelValues( "false", // label: valid "signature_invalid", // label: reason ).Inc() - } else { + default: metrics.WebhooksReceived.WithLabelValues( "false", // label: valid "unknown", // label: reason @@ -182,6 +184,7 @@ func (a *APIController) WSHandler(writer http.ResponseWriter, req *http.Request) return } + // nolint:golangci-lint,godox // TODO (gsamfira): Handle ExpiresAt. Right now, if a client uses // a valid token to authenticate, and keeps the websocket connection // open, it will allow that client to stream logs via websockets diff --git a/apiserver/controllers/enterprises.go b/apiserver/controllers/enterprises.go index 39abb223..d4b20826 100644 --- a/apiserver/controllers/enterprises.go +++ b/apiserver/controllers/enterprises.go @@ -19,11 +19,11 @@ import ( "log/slog" "net/http" + "github.com/gorilla/mux" + gErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/apiserver/params" runnerParams "github.com/cloudbase/garm/params" - - "github.com/gorilla/mux" ) // swagger:route POST /enterprises enterprises CreateEnterprise @@ -165,7 +165,6 @@ func (a *APIController) DeleteEnterpriseHandler(w http.ResponseWriter, r *http.R w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - } // swagger:route PUT /enterprises/{enterpriseID} enterprises UpdateEnterprise @@ -318,7 +317,6 @@ func (a *APIController) ListEnterprisePoolsHandler(w http.ResponseWriter, r *htt if err := json.NewEncoder(w).Encode(pools); err != nil { slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response") } - } // swagger:route GET /enterprises/{enterpriseID}/pools/{poolID} enterprises pools GetEnterprisePool @@ -414,7 +412,6 @@ func (a *APIController) DeleteEnterprisePoolHandler(w http.ResponseWriter, r *ht w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - } // swagger:route PUT /enterprises/{enterpriseID}/pools/{poolID} enterprises pools UpdateEnterprisePool diff --git a/apiserver/controllers/instances.go b/apiserver/controllers/instances.go index 6cf43dd9..b5504f76 100644 --- a/apiserver/controllers/instances.go +++ b/apiserver/controllers/instances.go @@ -20,11 +20,11 @@ import ( "net/http" "strconv" + "github.com/gorilla/mux" + gErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/apiserver/params" runnerParams "github.com/cloudbase/garm/params" - - "github.com/gorilla/mux" ) // swagger:route GET /pools/{poolID}/instances instances ListPoolInstances diff --git a/apiserver/controllers/metadata.go b/apiserver/controllers/metadata.go index 1b7e215d..4b112b17 100644 --- a/apiserver/controllers/metadata.go +++ b/apiserver/controllers/metadata.go @@ -20,8 +20,9 @@ import ( "log/slog" "net/http" - "github.com/cloudbase/garm/apiserver/params" "github.com/gorilla/mux" + + "github.com/cloudbase/garm/apiserver/params" ) func (a *APIController) InstanceGithubRegistrationTokenHandler(w http.ResponseWriter, r *http.Request) { diff --git a/apiserver/controllers/organizations.go b/apiserver/controllers/organizations.go index 8495d351..ca2ef3b5 100644 --- a/apiserver/controllers/organizations.go +++ b/apiserver/controllers/organizations.go @@ -20,11 +20,11 @@ import ( "net/http" "strconv" + "github.com/gorilla/mux" + gErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/apiserver/params" runnerParams "github.com/cloudbase/garm/params" - - "github.com/gorilla/mux" ) // swagger:route POST /organizations organizations CreateOrg @@ -174,7 +174,6 @@ func (a *APIController) DeleteOrgHandler(w http.ResponseWriter, r *http.Request) w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - } // swagger:route PUT /organizations/{orgID} organizations UpdateOrg @@ -423,7 +422,6 @@ func (a *APIController) DeleteOrgPoolHandler(w http.ResponseWriter, r *http.Requ w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - } // swagger:route PUT /organizations/{orgID}/pools/{poolID} organizations pools UpdateOrgPool diff --git a/apiserver/controllers/pools.go b/apiserver/controllers/pools.go index 3f7a81b1..901be588 100644 --- a/apiserver/controllers/pools.go +++ b/apiserver/controllers/pools.go @@ -19,11 +19,11 @@ import ( "log/slog" "net/http" + "github.com/gorilla/mux" + gErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/apiserver/params" runnerParams "github.com/cloudbase/garm/params" - - "github.com/gorilla/mux" ) // swagger:route GET /pools pools ListPools @@ -37,7 +37,6 @@ func (a *APIController) ListAllPoolsHandler(w http.ResponseWriter, r *http.Reque ctx := r.Context() pools, err := a.r.ListAllPools(ctx) - if err != nil { slog.With(slog.Any("error", err)).ErrorContext(ctx, "listing pools") handleError(ctx, w, err) diff --git a/apiserver/controllers/repositories.go b/apiserver/controllers/repositories.go index 6831dda4..7cc3c4f5 100644 --- a/apiserver/controllers/repositories.go +++ b/apiserver/controllers/repositories.go @@ -20,11 +20,11 @@ import ( "net/http" "strconv" + "github.com/gorilla/mux" + gErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/apiserver/params" runnerParams "github.com/cloudbase/garm/params" - - "github.com/gorilla/mux" ) // swagger:route POST /repositories repositories CreateRepo @@ -173,7 +173,6 @@ func (a *APIController) DeleteRepoHandler(w http.ResponseWriter, r *http.Request w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - } // swagger:route PUT /repositories/{repoID} repositories UpdateRepo @@ -422,7 +421,6 @@ func (a *APIController) DeleteRepoPoolHandler(w http.ResponseWriter, r *http.Req w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) - } // swagger:route PUT /repositories/{repoID}/pools/{poolID} repositories pools UpdateRepoPool diff --git a/apiserver/routers/routers.go b/apiserver/routers/routers.go index 5e6de6cd..5b4e69ab 100644 --- a/apiserver/routers/routers.go +++ b/apiserver/routers/routers.go @@ -49,7 +49,7 @@ import ( _ "expvar" // Register the expvar handlers "log/slog" "net/http" - _ "net/http/pprof" // Register the pprof handlers + _ "net/http/pprof" //nolint:golangci-lint,gosec // Register the pprof handlers "github.com/felixge/httpsnoop" "github.com/gorilla/mux" @@ -87,7 +87,6 @@ func requestLogger(h http.Handler) http.Handler { // gathers metrics from the upstream handlers metrics := httpsnoop.CaptureMetrics(h, w, r) - //prints log and metrics slog.Info( "access_log", slog.String("method", r.Method), diff --git a/auth/auth.go b/auth/auth.go index 8e1a98ac..4a4f957a 100644 --- a/auth/auth.go +++ b/auth/auth.go @@ -18,16 +18,16 @@ import ( "context" "time" + jwt "github.com/golang-jwt/jwt/v5" + "github.com/nbutton23/zxcvbn-go" + "github.com/pkg/errors" + "golang.org/x/crypto/bcrypt" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm-provider-common/util" "github.com/cloudbase/garm/config" "github.com/cloudbase/garm/database/common" "github.com/cloudbase/garm/params" - - jwt "github.com/golang-jwt/jwt/v5" - "github.com/nbutton23/zxcvbn-go" - "github.com/pkg/errors" - "golang.org/x/crypto/bcrypt" ) func NewAuthenticator(cfg config.JWTAuth, store common.Store) *Authenticator { @@ -58,6 +58,7 @@ func (a *Authenticator) GetJWTToken(ctx context.Context) (string, error) { claims := JWTClaims{ RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: expires, + // nolint:golangci-lint,godox // TODO: make this configurable Issuer: "garm", }, @@ -78,7 +79,6 @@ func (a *Authenticator) GetJWTToken(ctx context.Context) (string, error) { // GetJWTMetricsToken returns a JWT token that can be used to read metrics. // This token is not tied to a user, no user is stored in the db. func (a *Authenticator) GetJWTMetricsToken(ctx context.Context) (string, error) { - if !IsAdmin(ctx) { return "", runnerErrors.ErrUnauthorized } @@ -87,6 +87,7 @@ func (a *Authenticator) GetJWTMetricsToken(ctx context.Context) (string, error) if err != nil { return "", errors.Wrap(err, "generating random string") } + // nolint:golangci-lint,godox // TODO: currently this is the same TTL as the normal Token // maybe we should make this configurable // it's usually pretty nasty if the monitoring fails because the token expired @@ -97,6 +98,7 @@ func (a *Authenticator) GetJWTMetricsToken(ctx context.Context) (string, error) claims := JWTClaims{ RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: expires, + // nolint:golangci-lint,godox // TODO: make this configurable Issuer: "garm", }, diff --git a/auth/instance_middleware.go b/auth/instance_middleware.go index 1562b8b9..54fca249 100644 --- a/auth/instance_middleware.go +++ b/auth/instance_middleware.go @@ -22,15 +22,15 @@ import ( "strings" "time" + jwt "github.com/golang-jwt/jwt/v5" + "github.com/pkg/errors" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + commonParams "github.com/cloudbase/garm-provider-common/params" "github.com/cloudbase/garm/config" dbCommon "github.com/cloudbase/garm/database/common" "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" - - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - commonParams "github.com/cloudbase/garm-provider-common/params" - jwt "github.com/golang-jwt/jwt/v5" - "github.com/pkg/errors" ) // InstanceJWTClaims holds JWT claims @@ -111,6 +111,7 @@ func (amw *instanceMiddleware) claimsToContext(ctx context.Context, claims *Inst // Middleware implements the middleware interface func (amw *instanceMiddleware) Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // nolint:golangci-lint,godox // TODO: Log error details when authentication fails ctx := r.Context() authorizationHeader := r.Header.Get("authorization") @@ -132,7 +133,6 @@ func (amw *instanceMiddleware) Middleware(next http.Handler) http.Handler { } return []byte(amw.cfg.Secret), nil }) - if err != nil { invalidAuthResponse(ctx, w) return diff --git a/auth/jwt.go b/auth/jwt.go index 8516a02f..d463df2c 100644 --- a/auth/jwt.go +++ b/auth/jwt.go @@ -22,12 +22,12 @@ import ( "net/http" "strings" + jwt "github.com/golang-jwt/jwt/v5" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" apiParams "github.com/cloudbase/garm/apiserver/params" "github.com/cloudbase/garm/config" dbCommon "github.com/cloudbase/garm/database/common" - - jwt "github.com/golang-jwt/jwt/v5" ) // JWTClaims holds JWT claims @@ -87,6 +87,7 @@ func invalidAuthResponse(ctx context.Context, w http.ResponseWriter) { // Middleware implements the middleware interface func (amw *jwtMiddleware) Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + // nolint:golangci-lint,godox // TODO: Log error details when authentication fails ctx := r.Context() authorizationHeader := r.Header.Get("authorization") @@ -108,7 +109,6 @@ func (amw *jwtMiddleware) Middleware(next http.Handler) http.Handler { } return []byte(amw.cfg.Secret), nil }) - if err != nil { invalidAuthResponse(ctx, w) return diff --git a/auth/metrics.go b/auth/metrics.go index 3be4577a..55cede44 100644 --- a/auth/metrics.go +++ b/auth/metrics.go @@ -6,9 +6,9 @@ import ( "net/http" "strings" - "github.com/cloudbase/garm/config" - jwt "github.com/golang-jwt/jwt/v5" + + "github.com/cloudbase/garm/config" ) type MetricsMiddleware struct { @@ -23,7 +23,6 @@ func NewMetricsMiddleware(cfg config.JWTAuth) (*MetricsMiddleware, error) { func (m *MetricsMiddleware) Middleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - ctx := r.Context() authorizationHeader := r.Header.Get("authorization") if authorizationHeader == "" { @@ -44,7 +43,6 @@ func (m *MetricsMiddleware) Middleware(next http.Handler) http.Handler { } return []byte(m.cfg.Secret), nil }) - if err != nil { invalidAuthResponse(ctx, w) return diff --git a/cmd/garm-cli/cmd/controller_info.go b/cmd/garm-cli/cmd/controller_info.go index 0a42ae1e..67ef2b86 100644 --- a/cmd/garm-cli/cmd/controller_info.go +++ b/cmd/garm-cli/cmd/controller_info.go @@ -17,10 +17,11 @@ package cmd import ( "fmt" - apiClientControllerInfo "github.com/cloudbase/garm/client/controller_info" - "github.com/cloudbase/garm/params" "github.com/jedib0t/go-pretty/v6/table" "github.com/spf13/cobra" + + apiClientControllerInfo "github.com/cloudbase/garm/client/controller_info" + "github.com/cloudbase/garm/params" ) var infoCmd = &cobra.Command{ @@ -36,7 +37,7 @@ var infoShowCmd = &cobra.Command{ Short: "Show information", Long: `Show information about the current controller.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } diff --git a/cmd/garm-cli/cmd/credentials.go b/cmd/garm-cli/cmd/credentials.go index ec73c95f..72bf4ec3 100644 --- a/cmd/garm-cli/cmd/credentials.go +++ b/cmd/garm-cli/cmd/credentials.go @@ -17,11 +17,11 @@ package cmd import ( "fmt" - apiClientCreds "github.com/cloudbase/garm/client/credentials" - "github.com/cloudbase/garm/params" - "github.com/jedib0t/go-pretty/v6/table" "github.com/spf13/cobra" + + apiClientCreds "github.com/cloudbase/garm/client/credentials" + "github.com/cloudbase/garm/params" ) // credentialsCmd represents the credentials command @@ -34,7 +34,7 @@ config file. Currently, github personal tokens are configured statically in the config file of the garm service. This command lists the names of those credentials, -which in turn can be used to define pools of runners withing repositories.`, +which in turn can be used to define pools of runners within repositories.`, Run: nil, } @@ -44,9 +44,9 @@ func init() { Use: "list", Aliases: []string{"ls"}, Short: "List configured github credentials", - Long: `List the names of the github personal access tokens availabe to the garm.`, + Long: `List the names of the github personal access tokens available to the garm.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } diff --git a/cmd/garm-cli/cmd/enterprise.go b/cmd/garm-cli/cmd/enterprise.go index fe49545a..b01b0413 100644 --- a/cmd/garm-cli/cmd/enterprise.go +++ b/cmd/garm-cli/cmd/enterprise.go @@ -17,11 +17,11 @@ package cmd import ( "fmt" - apiClientEnterprises "github.com/cloudbase/garm/client/enterprises" - "github.com/cloudbase/garm/params" - "github.com/jedib0t/go-pretty/v6/table" "github.com/spf13/cobra" + + apiClientEnterprises "github.com/cloudbase/garm/client/enterprises" + "github.com/cloudbase/garm/params" ) var ( @@ -50,7 +50,7 @@ var enterpriseAddCmd = &cobra.Command{ Short: "Add enterprise", Long: `Add a new enterprise to the manager.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } @@ -76,7 +76,7 @@ var enterpriseListCmd = &cobra.Command{ Short: "List enterprises", Long: `List all configured enterprises that are currently managed.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } @@ -96,7 +96,7 @@ var enterpriseShowCmd = &cobra.Command{ Short: "Show details for one enterprise", Long: `Displays detailed information about a single enterprise.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -123,7 +123,7 @@ var enterpriseDeleteCmd = &cobra.Command{ Short: "Removes one enterprise", Long: `Delete one enterprise from the manager.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -147,7 +147,7 @@ var enterpriseUpdateCmd = &cobra.Command{ Short: "Update enterprise", Long: `Update enterprise credentials or webhook secret.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -175,7 +175,6 @@ var enterpriseUpdateCmd = &cobra.Command{ } func init() { - enterpriseAddCmd.Flags().StringVar(&enterpriseName, "name", "", "The name of the enterprise") enterpriseAddCmd.Flags().StringVar(&enterpriseWebhookSecret, "webhook-secret", "", "The webhook secret for this enterprise") enterpriseAddCmd.Flags().StringVar(&enterpriseCreds, "credentials", "", "Credentials name. See credentials list.") diff --git a/cmd/garm-cli/cmd/init.go b/cmd/garm-cli/cmd/init.go index b85c5a8f..acdbda5a 100644 --- a/cmd/garm-cli/cmd/init.go +++ b/cmd/garm-cli/cmd/init.go @@ -18,15 +18,15 @@ import ( "fmt" "strings" - "github.com/cloudbase/garm/cmd/garm-cli/common" - "github.com/cloudbase/garm/cmd/garm-cli/config" - "github.com/cloudbase/garm/params" - - apiClientFirstRun "github.com/cloudbase/garm/client/first_run" - apiClientLogin "github.com/cloudbase/garm/client/login" "github.com/jedib0t/go-pretty/v6/table" "github.com/pkg/errors" "github.com/spf13/cobra" + + apiClientFirstRun "github.com/cloudbase/garm/client/first_run" + apiClientLogin "github.com/cloudbase/garm/client/login" + "github.com/cloudbase/garm/cmd/garm-cli/common" + "github.com/cloudbase/garm/cmd/garm-cli/config" + "github.com/cloudbase/garm/params" ) // initCmd represents the init command @@ -45,7 +45,7 @@ Example usage: garm-cli init --name=dev --url=https://runner.example.com --username=admin --password=superSecretPassword `, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if cfg != nil { if cfg.HasManager(loginProfileName) { return fmt.Errorf("a manager with name %s already exists in your local config", loginProfileName) @@ -66,7 +66,7 @@ garm-cli init --name=dev --url=https://runner.example.com --username=admin --pas url := strings.TrimSuffix(loginURL, "/") - initApiClient(url, "") + initAPIClient(url, "") response, err := apiCli.FirstRun.FirstRun(newUserReq, authToken) if err != nil { diff --git a/cmd/garm-cli/cmd/jobs.go b/cmd/garm-cli/cmd/jobs.go index 36f61e8e..c8505222 100644 --- a/cmd/garm-cli/cmd/jobs.go +++ b/cmd/garm-cli/cmd/jobs.go @@ -18,11 +18,12 @@ import ( "fmt" "strings" - apiClientJobs "github.com/cloudbase/garm/client/jobs" - "github.com/cloudbase/garm/params" "github.com/google/uuid" "github.com/jedib0t/go-pretty/v6/table" "github.com/spf13/cobra" + + apiClientJobs "github.com/cloudbase/garm/client/jobs" + "github.com/cloudbase/garm/params" ) // runnerCmd represents the runner command @@ -40,7 +41,7 @@ var jobsListCmd = &cobra.Command{ Short: "List jobs", Long: `List all jobs currently recorded in the system.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } diff --git a/cmd/garm-cli/cmd/log.go b/cmd/garm-cli/cmd/log.go index 19708afc..1dab7c1d 100644 --- a/cmd/garm-cli/cmd/log.go +++ b/cmd/garm-cli/cmd/log.go @@ -11,11 +11,11 @@ import ( "os/signal" "time" - "github.com/cloudbase/garm-provider-common/util" - apiParams "github.com/cloudbase/garm/apiserver/params" - "github.com/gorilla/websocket" "github.com/spf13/cobra" + + "github.com/cloudbase/garm-provider-common/util" + apiParams "github.com/cloudbase/garm/apiserver/params" ) var logCmd = &cobra.Command{ @@ -23,7 +23,7 @@ var logCmd = &cobra.Command{ SilenceUsage: true, Short: "Stream garm log", Long: `Stream all garm logging to the terminal.`, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { interrupt := make(chan os.Signal, 1) signal.Notify(interrupt, os.Interrupt) diff --git a/cmd/garm-cli/cmd/metrics.go b/cmd/garm-cli/cmd/metrics.go index e79d9456..ea1fd7ca 100644 --- a/cmd/garm-cli/cmd/metrics.go +++ b/cmd/garm-cli/cmd/metrics.go @@ -17,8 +17,9 @@ package cmd import ( "fmt" - apiClientMetricToken "github.com/cloudbase/garm/client/metrics_token" "github.com/spf13/cobra" + + apiClientMetricToken "github.com/cloudbase/garm/client/metrics_token" ) // orgPoolCmd represents the pool command @@ -35,7 +36,7 @@ var metricsTokenCreateCmd = &cobra.Command{ Short: "Create a metrics token", Long: `Create a metrics token.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } diff --git a/cmd/garm-cli/cmd/organization.go b/cmd/garm-cli/cmd/organization.go index d833e2dd..2b5def34 100644 --- a/cmd/garm-cli/cmd/organization.go +++ b/cmd/garm-cli/cmd/organization.go @@ -17,12 +17,12 @@ package cmd import ( "fmt" + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" + "github.com/cloudbase/garm-provider-common/util" apiClientOrgs "github.com/cloudbase/garm/client/organizations" "github.com/cloudbase/garm/params" - - "github.com/jedib0t/go-pretty/v6/table" - "github.com/spf13/cobra" ) var ( @@ -62,7 +62,7 @@ var orgWebhookInstallCmd = &cobra.Command{ Short: "Install webhook", Long: `Install webhook for an organization.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -92,7 +92,7 @@ var orgHookInfoShowCmd = &cobra.Command{ Short: "Show webhook info", Long: `Show webhook info for an organization.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -120,7 +120,7 @@ var orgWebhookUninstallCmd = &cobra.Command{ Short: "Uninstall webhook", Long: `Uninstall webhook for an organization.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -148,7 +148,7 @@ var orgAddCmd = &cobra.Command{ Short: "Add organization", Long: `Add a new organization to the manager.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } @@ -199,7 +199,7 @@ var orgUpdateCmd = &cobra.Command{ Short: "Update organization", Long: `Update organization credentials or webhook secret.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -232,7 +232,7 @@ var orgListCmd = &cobra.Command{ Short: "List organizations", Long: `List all configured organizations that are currently managed.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } @@ -252,7 +252,7 @@ var orgShowCmd = &cobra.Command{ Short: "Show details for one organization", Long: `Displays detailed information about a single organization.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -279,7 +279,7 @@ var orgDeleteCmd = &cobra.Command{ Short: "Removes one organization", Long: `Delete one organization from the manager.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -300,7 +300,6 @@ var orgDeleteCmd = &cobra.Command{ } func init() { - orgAddCmd.Flags().StringVar(&orgName, "name", "", "The name of the organization") orgAddCmd.Flags().StringVar(&orgWebhookSecret, "webhook-secret", "", "The webhook secret for this organization") orgAddCmd.Flags().StringVar(&orgCreds, "credentials", "", "Credentials name. See credentials list.") diff --git a/cmd/garm-cli/cmd/pool.go b/cmd/garm-cli/cmd/pool.go index 4820cabd..31fe326d 100644 --- a/cmd/garm-cli/cmd/pool.go +++ b/cmd/garm-cli/cmd/pool.go @@ -20,18 +20,16 @@ import ( "os" "strings" - apiClientEnterprises "github.com/cloudbase/garm/client/enterprises" - apiClientOrgs "github.com/cloudbase/garm/client/organizations" - apiClientPools "github.com/cloudbase/garm/client/pools" - apiClientRepos "github.com/cloudbase/garm/client/repositories" - - "github.com/cloudbase/garm/params" - "github.com/jedib0t/go-pretty/v6/table" "github.com/pkg/errors" "github.com/spf13/cobra" commonParams "github.com/cloudbase/garm-provider-common/params" + apiClientEnterprises "github.com/cloudbase/garm/client/enterprises" + apiClientOrgs "github.com/cloudbase/garm/client/organizations" + apiClientPools "github.com/cloudbase/garm/client/pools" + apiClientRepos "github.com/cloudbase/garm/client/repositories" + "github.com/cloudbase/garm/params" ) var ( @@ -141,7 +139,7 @@ var poolShowCmd = &cobra.Command{ Short: "Show details for a runner", Long: `Displays a detailed view of a single runner.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -171,7 +169,7 @@ var poolDeleteCmd = &cobra.Command{ Short: "Delete pool by ID", Long: `Delete one pool by referencing it's ID, regardless of repo or org.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -199,7 +197,7 @@ var poolAddCmd = &cobra.Command{ Short: "Add pool", Long: `Add a new pool to a repository or organization.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } @@ -381,8 +379,8 @@ explicitly remove them using the runner delete command. func init() { poolListCmd.Flags().StringVarP(&poolRepository, "repo", "r", "", "List all pools within this repository.") - poolListCmd.Flags().StringVarP(&poolOrganization, "org", "o", "", "List all pools withing this organization.") - poolListCmd.Flags().StringVarP(&poolEnterprise, "enterprise", "e", "", "List all pools withing this enterprise.") + poolListCmd.Flags().StringVarP(&poolOrganization, "org", "o", "", "List all pools within this organization.") + poolListCmd.Flags().StringVarP(&poolEnterprise, "enterprise", "e", "", "List all pools within this enterprise.") poolListCmd.Flags().BoolVarP(&poolAll, "all", "a", false, "List all pools, regardless of org or repo.") poolListCmd.MarkFlagsMutuallyExclusive("repo", "org", "all", "enterprise") @@ -421,8 +419,8 @@ func init() { poolAddCmd.MarkFlagRequired("tags") //nolint poolAddCmd.Flags().StringVarP(&poolRepository, "repo", "r", "", "Add the new pool within this repository.") - poolAddCmd.Flags().StringVarP(&poolOrganization, "org", "o", "", "Add the new pool withing this organization.") - poolAddCmd.Flags().StringVarP(&poolEnterprise, "enterprise", "e", "", "Add the new pool withing this enterprise.") + poolAddCmd.Flags().StringVarP(&poolOrganization, "org", "o", "", "Add the new pool within this organization.") + poolAddCmd.Flags().StringVarP(&poolEnterprise, "enterprise", "e", "", "Add the new pool within this enterprise.") poolAddCmd.MarkFlagsMutuallyExclusive("repo", "org", "enterprise") poolAddCmd.MarkFlagsMutuallyExclusive("extra-specs-file", "extra-specs") @@ -453,13 +451,13 @@ func asRawMessage(data []byte) (json.RawMessage, error) { return nil, errors.Wrap(err, "decoding extra specs") } - var asRawJson json.RawMessage + var asRawJSON json.RawMessage var err error - asRawJson, err = json.Marshal(unmarshaled) + asRawJSON, err = json.Marshal(unmarshaled) if err != nil { return nil, errors.Wrap(err, "marshaling json") } - return asRawJson, nil + return asRawJSON, nil } func formatPools(pools []params.Pool) { @@ -475,13 +473,14 @@ func formatPools(pools []params.Pool) { var belongsTo string var level string - if pool.RepoID != "" && pool.RepoName != "" { + switch { + case pool.RepoID != "" && pool.RepoName != "": belongsTo = pool.RepoName level = "repo" - } else if pool.OrgID != "" && pool.OrgName != "" { + case pool.OrgID != "" && pool.OrgName != "": belongsTo = pool.OrgName level = "org" - } else if pool.EnterpriseID != "" && pool.EnterpriseName != "" { + case pool.EnterpriseID != "" && pool.EnterpriseName != "": belongsTo = pool.EnterpriseName level = "enterprise" } @@ -505,13 +504,14 @@ func formatOnePool(pool params.Pool) { var belongsTo string var level string - if pool.RepoID != "" && pool.RepoName != "" { + switch { + case pool.RepoID != "" && pool.RepoName != "": belongsTo = pool.RepoName level = "repo" - } else if pool.OrgID != "" && pool.OrgName != "" { + case pool.OrgID != "" && pool.OrgName != "": belongsTo = pool.OrgName level = "org" - } else if pool.EnterpriseID != "" && pool.EnterpriseName != "" { + case pool.EnterpriseID != "" && pool.EnterpriseName != "": belongsTo = pool.EnterpriseName level = "enterprise" } @@ -532,7 +532,7 @@ func formatOnePool(pool params.Pool) { t.AppendRow(table.Row{"Enabled", pool.Enabled}) t.AppendRow(table.Row{"Runner Prefix", pool.GetRunnerPrefix()}) t.AppendRow(table.Row{"Extra specs", string(pool.ExtraSpecs)}) - t.AppendRow(table.Row{"GitHub Runner Group", string(pool.GitHubRunnerGroup)}) + t.AppendRow(table.Row{"GitHub Runner Group", pool.GitHubRunnerGroup}) if len(pool.Instances) > 0 { for _, instance := range pool.Instances { diff --git a/cmd/garm-cli/cmd/profile.go b/cmd/garm-cli/cmd/profile.go index 71843df8..0ec28ec0 100644 --- a/cmd/garm-cli/cmd/profile.go +++ b/cmd/garm-cli/cmd/profile.go @@ -18,13 +18,13 @@ import ( "fmt" "strings" + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" + apiClientLogin "github.com/cloudbase/garm/client/login" "github.com/cloudbase/garm/cmd/garm-cli/common" "github.com/cloudbase/garm/cmd/garm-cli/config" "github.com/cloudbase/garm/params" - - "github.com/jedib0t/go-pretty/v6/table" - "github.com/spf13/cobra" ) var ( @@ -55,7 +55,7 @@ This command will list all currently defined profiles in the local configuration file of the garm client. `, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } @@ -76,7 +76,7 @@ var profileDeleteCmd = &cobra.Command{ Short: "Delete profile", Long: `Delete a profile from the local CLI configuration.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -101,7 +101,7 @@ var poolSwitchCmd = &cobra.Command{ Short: "Switch to a different profile", Long: `Switch the CLI to a different profile.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -132,7 +132,7 @@ var profileAddCmd = &cobra.Command{ Short: "Add profile", Long: `Create a profile for a new garm installation.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if cfg != nil { if cfg.HasManager(loginProfileName) { return fmt.Errorf("a manager with name %s already exists in your local config", loginProfileName) @@ -145,7 +145,7 @@ var profileAddCmd = &cobra.Command{ url := strings.TrimSuffix(loginURL, "/") - initApiClient(url, "") + initAPIClient(url, "") newLoginParamsReq := apiClientLogin.NewLoginParams() newLoginParamsReq.Body = params.PasswordLoginParams{ @@ -180,7 +180,7 @@ This command will refresh the bearer token associated with an already defined ga installation, by performing a login. `, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } diff --git a/cmd/garm-cli/cmd/provider.go b/cmd/garm-cli/cmd/provider.go index e9635dd0..eef6a421 100644 --- a/cmd/garm-cli/cmd/provider.go +++ b/cmd/garm-cli/cmd/provider.go @@ -17,11 +17,11 @@ package cmd import ( "fmt" - apiClientProviders "github.com/cloudbase/garm/client/providers" - "github.com/cloudbase/garm/params" - "github.com/jedib0t/go-pretty/v6/table" "github.com/spf13/cobra" + + apiClientProviders "github.com/cloudbase/garm/client/providers" + "github.com/cloudbase/garm/params" ) // providerCmd represents the provider command @@ -45,7 +45,7 @@ func init() { Short: "List all configured providers", Long: `List all cloud providers configured with the service.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } diff --git a/cmd/garm-cli/cmd/repository.go b/cmd/garm-cli/cmd/repository.go index 8482264b..a603988b 100644 --- a/cmd/garm-cli/cmd/repository.go +++ b/cmd/garm-cli/cmd/repository.go @@ -17,12 +17,12 @@ package cmd import ( "fmt" + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" + "github.com/cloudbase/garm-provider-common/util" apiClientRepos "github.com/cloudbase/garm/client/repositories" "github.com/cloudbase/garm/params" - - "github.com/jedib0t/go-pretty/v6/table" - "github.com/spf13/cobra" ) var ( @@ -63,7 +63,7 @@ var repoWebhookInstallCmd = &cobra.Command{ Short: "Install webhook", Long: `Install webhook for a repository.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -93,7 +93,7 @@ var repoHookInfoShowCmd = &cobra.Command{ Short: "Show webhook info", Long: `Show webhook info for a repository.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -121,7 +121,7 @@ var repoWebhookUninstallCmd = &cobra.Command{ Short: "Uninstall webhook", Long: `Uninstall webhook for a repository.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -149,7 +149,7 @@ var repoAddCmd = &cobra.Command{ Short: "Add repository", Long: `Add a new repository to the manager.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } @@ -200,9 +200,9 @@ var repoListCmd = &cobra.Command{ Use: "list", Aliases: []string{"ls"}, Short: "List repositories", - Long: `List all configured respositories that are currently managed.`, + Long: `List all configured repositories that are currently managed.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, _ []string) error { if needsInit { return errNeedsInitError } @@ -222,7 +222,7 @@ var repoUpdateCmd = &cobra.Command{ Short: "Update repository", Long: `Update repository credentials or webhook secret.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -255,7 +255,7 @@ var repoShowCmd = &cobra.Command{ Short: "Show details for one repository", Long: `Displays detailed information about a single repository.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -282,7 +282,7 @@ var repoDeleteCmd = &cobra.Command{ Short: "Removes one repository", Long: `Delete one repository from the manager.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -303,7 +303,6 @@ var repoDeleteCmd = &cobra.Command{ } func init() { - repoAddCmd.Flags().StringVar(&repoOwner, "owner", "", "The owner of this repository") repoAddCmd.Flags().StringVar(&repoName, "name", "", "The name of the repository") repoAddCmd.Flags().StringVar(&repoWebhookSecret, "webhook-secret", "", "The webhook secret for this repository") diff --git a/cmd/garm-cli/cmd/root.go b/cmd/garm-cli/cmd/root.go index 72ecddc4..86bd47ac 100644 --- a/cmd/garm-cli/cmd/root.go +++ b/cmd/garm-cli/cmd/root.go @@ -19,14 +19,14 @@ import ( "net/url" "os" + "github.com/go-openapi/runtime" + openapiRuntimeClient "github.com/go-openapi/runtime/client" + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" + apiClient "github.com/cloudbase/garm/client" "github.com/cloudbase/garm/cmd/garm-cli/config" "github.com/cloudbase/garm/params" - "github.com/go-openapi/runtime" - "github.com/jedib0t/go-pretty/v6/table" - - openapiRuntimeClient "github.com/go-openapi/runtime/client" - "github.com/spf13/cobra" ) var Version string @@ -60,24 +60,24 @@ func Execute() { } } -func initApiClient(baseUrl, token string) { - baseUrlParsed, err := url.Parse(baseUrl) +func initAPIClient(baseURL, token string) { + baseURLParsed, err := url.Parse(baseURL) if err != nil { - fmt.Printf("Failed to parse base url %s: %s", baseUrl, err) + fmt.Printf("Failed to parse base url %s: %s", baseURL, err) os.Exit(1) } - apiPath, err := url.JoinPath(baseUrlParsed.Path, apiClient.DefaultBasePath) + apiPath, err := url.JoinPath(baseURLParsed.Path, apiClient.DefaultBasePath) if err != nil { - fmt.Printf("Failed to join base url path %s with %s: %s", baseUrlParsed.Path, apiClient.DefaultBasePath, err) + fmt.Printf("Failed to join base url path %s with %s: %s", baseURLParsed.Path, apiClient.DefaultBasePath, err) os.Exit(1) } if debug { os.Setenv("SWAGGER_DEBUG", "true") } transportCfg := apiClient.DefaultTransportConfig(). - WithHost(baseUrlParsed.Host). + WithHost(baseURLParsed.Host). WithBasePath(apiPath). - WithSchemes([]string{baseUrlParsed.Scheme}) + WithSchemes([]string{baseURLParsed.Scheme}) apiCli = apiClient.NewHTTPClientWithConfig(nil, transportCfg) authToken = openapiRuntimeClient.BearerToken(token) } @@ -98,7 +98,7 @@ func initConfig() { mgr = cfg.Managers[0] } } - initApiClient(mgr.BaseURL, mgr.Token) + initAPIClient(mgr.BaseURL, mgr.Token) } func formatOneHookInfo(hook params.HookInfo) { diff --git a/cmd/garm-cli/cmd/runner.go b/cmd/garm-cli/cmd/runner.go index 5b7d07c5..b3c00ae8 100644 --- a/cmd/garm-cli/cmd/runner.go +++ b/cmd/garm-cli/cmd/runner.go @@ -18,14 +18,14 @@ import ( "fmt" "os" - "github.com/cloudbase/garm/params" + "github.com/jedib0t/go-pretty/v6/table" + "github.com/spf13/cobra" apiClientEnterprises "github.com/cloudbase/garm/client/enterprises" apiClientInstances "github.com/cloudbase/garm/client/instances" apiClientOrgs "github.com/cloudbase/garm/client/organizations" apiClientRepos "github.com/cloudbase/garm/client/repositories" - "github.com/jedib0t/go-pretty/v6/table" - "github.com/spf13/cobra" + "github.com/cloudbase/garm/params" ) var ( @@ -139,7 +139,7 @@ var runnerShowCmd = &cobra.Command{ Short: "Show details for a runner", Long: `Displays a detailed view of a single runner.`, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -178,7 +178,7 @@ NOTE: An active runner cannot be removed from Github. You will have to either cancel the workflow or wait for it to finish. `, SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(_ *cobra.Command, args []string) error { if needsInit { return errNeedsInitError } @@ -199,8 +199,8 @@ to either cancel the workflow or wait for it to finish. func init() { runnerListCmd.Flags().StringVarP(&runnerRepository, "repo", "r", "", "List all runners from all pools within this repository.") - runnerListCmd.Flags().StringVarP(&runnerOrganization, "org", "o", "", "List all runners from all pools withing this organization.") - runnerListCmd.Flags().StringVarP(&runnerEnterprise, "enterprise", "e", "", "List all runners from all pools withing this enterprise.") + runnerListCmd.Flags().StringVarP(&runnerOrganization, "org", "o", "", "List all runners from all pools within this organization.") + runnerListCmd.Flags().StringVarP(&runnerEnterprise, "enterprise", "e", "", "List all runners from all pools within this enterprise.") runnerListCmd.Flags().BoolVarP(&runnerAll, "all", "a", false, "List all runners, regardless of org or repo.") runnerListCmd.MarkFlagsMutuallyExclusive("repo", "org", "enterprise", "all") diff --git a/cmd/garm-cli/cmd/version.go b/cmd/garm-cli/cmd/version.go index 99253aed..4d209b3d 100644 --- a/cmd/garm-cli/cmd/version.go +++ b/cmd/garm-cli/cmd/version.go @@ -25,7 +25,7 @@ var versionCmd = &cobra.Command{ Use: "version", SilenceUsage: true, Short: "Print version and exit", - Run: func(cmd *cobra.Command, args []string) { + Run: func(_ *cobra.Command, _ []string) { fmt.Println(Version) }, } diff --git a/cmd/garm-cli/common/common.go b/cmd/garm-cli/common/common.go index 8164b9a7..b3850e31 100644 --- a/cmd/garm-cli/common/common.go +++ b/cmd/garm-cli/common/common.go @@ -39,7 +39,6 @@ func PromptPassword(label string) (string, error) { Mask: '*', } result, err := prompt.Run() - if err != nil { return "", err } @@ -59,7 +58,6 @@ func PromptString(label string) (string, error) { Validate: validate, } result, err := prompt.Run() - if err != nil { return "", err } diff --git a/cmd/garm-cli/config/home_nix.go b/cmd/garm-cli/config/home_nix.go index 92c99bad..27aed4f8 100644 --- a/cmd/garm-cli/config/home_nix.go +++ b/cmd/garm-cli/config/home_nix.go @@ -12,7 +12,6 @@ import ( func getHomeDir() (string, error) { home, err := os.UserHomeDir() - if err != nil { return "", errors.Wrap(err, "fetching home dir") } diff --git a/cmd/garm/main.go b/cmd/garm/main.go index df7a82e8..ad80c521 100644 --- a/cmd/garm/main.go +++ b/cmd/garm/main.go @@ -28,6 +28,11 @@ import ( "syscall" "time" + "github.com/gorilla/handlers" + "github.com/gorilla/mux" + "github.com/pkg/errors" + lumberjack "gopkg.in/natefinch/lumberjack.v2" + "github.com/cloudbase/garm-provider-common/util" "github.com/cloudbase/garm/apiserver/controllers" "github.com/cloudbase/garm/apiserver/routers" @@ -36,16 +41,11 @@ import ( "github.com/cloudbase/garm/database" "github.com/cloudbase/garm/database/common" "github.com/cloudbase/garm/metrics" - "github.com/cloudbase/garm/runner" + "github.com/cloudbase/garm/runner" //nolint:typecheck runnerMetrics "github.com/cloudbase/garm/runner/metrics" garmUtil "github.com/cloudbase/garm/util" "github.com/cloudbase/garm/util/appdefaults" "github.com/cloudbase/garm/websocket" - lumberjack "gopkg.in/natefinch/lumberjack.v2" - - "github.com/gorilla/handlers" - "github.com/gorilla/mux" - "github.com/pkg/errors" ) var ( @@ -98,7 +98,7 @@ func setupLogging(ctx context.Context, logCfg config.Logging, hub *websocket.Hub } }() - var writers []io.Writer = []io.Writer{ + writers := []io.Writer{ logWriter, } @@ -140,7 +140,6 @@ func setupLogging(ctx context.Context, logCfg config.Logging, hub *websocket.Hub Handler: han, } slog.SetDefault(slog.New(wrapped)) - } func main() { @@ -154,7 +153,7 @@ func main() { cfg, err := config.NewConfig(*conf) if err != nil { - log.Fatalf("Fetching config: %+v", err) + log.Fatalf("Fetching config: %+v", err) //nolint:gocritic } logCfg := cfg.GetLoggingConfig() @@ -241,6 +240,8 @@ func main() { methodsOk := handlers.AllowedMethods([]string{"GET", "HEAD", "POST", "PUT", "OPTIONS", "DELETE"}) headersOk := handlers.AllowedHeaders([]string{"X-Requested-With", "Content-Type", "Authorization"}) + // nolint:golangci-lint,gosec + // G112: Potential Slowloris Attack because ReadHeaderTimeout is not configured in the http.Server srv := &http.Server{ Addr: cfg.APIServer.BindAddress(), // Pass our instance of gorilla/mux in. diff --git a/config/config.go b/config/config.go index a12b91a9..bea1b5b8 100644 --- a/config/config.go +++ b/config/config.go @@ -26,15 +26,18 @@ import ( "time" "github.com/BurntSushi/toml" - "github.com/cloudbase/garm/params" - "github.com/cloudbase/garm/util/appdefaults" zxcvbn "github.com/nbutton23/zxcvbn-go" "github.com/pkg/errors" + + "github.com/cloudbase/garm/params" + "github.com/cloudbase/garm/util/appdefaults" ) -type DBBackendType string -type LogLevel string -type LogFormat string +type ( + DBBackendType string + LogLevel string + LogFormat string +) const ( // MySQLBackend represents the MySQL DB backend @@ -120,7 +123,7 @@ func (c *Config) Validate() error { if err := provider.Validate(); err != nil { return errors.Wrap(err, "validating provider") } - providerNames[provider.Name] += 1 + providerNames[provider.Name]++ } for name, count := range providerNames { @@ -543,6 +546,7 @@ func (d *timeToLive) Duration() time.Duration { slog.With(slog.Any("error", err)).Error("failed to parse duration") return appdefaults.DefaultJWTTTL } + // nolint:golangci-lint,godox // TODO(gabriel-samfira): should we have a minimum TTL? if duration < appdefaults.DefaultJWTTTL { return appdefaults.DefaultJWTTTL diff --git a/config/config_test.go b/config/config_test.go index 2281d196..2d2cf34d 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -20,11 +20,13 @@ import ( "testing" "time" - "github.com/cloudbase/garm/util/appdefaults" "github.com/stretchr/testify/require" + + "github.com/cloudbase/garm/util/appdefaults" ) var ( + // nolint: golangci-lint,gosec EncryptionPassphrase = "bocyasicgatEtenOubwonIbsudNutDom" WeakEncryptionPassphrase = "1234567890abcdefghijklmnopqrstuv" ) @@ -392,7 +394,6 @@ func TestGormParams(t *testing.T) { require.Nil(t, err) require.Equal(t, MySQLBackend, dbType) require.Equal(t, "test:test@tcp(127.0.0.1)/garm?charset=utf8&parseTime=True&loc=Local&timeout=5s", uri) - } func TestSQLiteConfig(t *testing.T) { diff --git a/config/external.go b/config/external.go index 8368b13c..66458868 100644 --- a/config/external.go +++ b/config/external.go @@ -20,9 +20,9 @@ import ( "path/filepath" "strings" - "github.com/cloudbase/garm-provider-common/util/exec" - "github.com/pkg/errors" + + "github.com/cloudbase/garm-provider-common/util/exec" ) // External represents the config for an external provider. diff --git a/config/external_test.go b/config/external_test.go index 30085726..17dc04ba 100644 --- a/config/external_test.go +++ b/config/external_test.go @@ -31,7 +31,8 @@ func getDefaultExternalConfig(t *testing.T) External { } t.Cleanup(func() { os.RemoveAll(dir) }) - err = os.WriteFile(filepath.Join(dir, "garm-external-provider"), []byte{}, 0755) + // nolint:golangci-lint,gosec + err = os.WriteFile(filepath.Join(dir, "garm-external-provider"), []byte{}, 0o755) if err != nil { t.Fatalf("failed to write file: %s", err) } diff --git a/database/common/common.go b/database/common/common.go index dcc05882..6f8dc820 100644 --- a/database/common/common.go +++ b/database/common/common.go @@ -28,7 +28,7 @@ type RepoStore interface { DeleteRepository(ctx context.Context, repoID string) error UpdateRepository(ctx context.Context, repoID string, param params.UpdateEntityParams) (params.Repository, error) - CreateRepositoryPool(ctx context.Context, repoId string, param params.CreatePoolParams) (params.Pool, error) + CreateRepositoryPool(ctx context.Context, repoID string, param params.CreatePoolParams) (params.Pool, error) GetRepositoryPool(ctx context.Context, repoID, poolID string) (params.Pool, error) DeleteRepositoryPool(ctx context.Context, repoID, poolID string) error @@ -47,7 +47,7 @@ type OrgStore interface { DeleteOrganization(ctx context.Context, orgID string) error UpdateOrganization(ctx context.Context, orgID string, param params.UpdateEntityParams) (params.Organization, error) - CreateOrganizationPool(ctx context.Context, orgId string, param params.CreatePoolParams) (params.Pool, error) + CreateOrganizationPool(ctx context.Context, orgID string, param params.CreatePoolParams) (params.Pool, error) GetOrganizationPool(ctx context.Context, orgID, poolID string) (params.Pool, error) DeleteOrganizationPool(ctx context.Context, orgID, poolID string) error UpdateOrganizationPool(ctx context.Context, orgID, poolID string, param params.UpdatePoolParams) (params.Pool, error) @@ -77,6 +77,7 @@ type EnterpriseStore interface { type PoolStore interface { // Probably a bad idea without some king of filter or at least pagination + // nolint:golangci-lint,godox // TODO: add filter/pagination ListAllPools(ctx context.Context) ([]params.Pool, error) GetPoolByID(ctx context.Context, poolID string) (params.Pool, error) @@ -104,6 +105,8 @@ type InstanceStore interface { UpdateInstance(ctx context.Context, instanceID string, param params.UpdateInstanceParams) (params.Instance, error) // Probably a bad idea without some king of filter or at least pagination + // + // nolint:golangci-lint,godox // TODO: add filter/pagination ListAllInstances(ctx context.Context) ([]params.Instance, error) diff --git a/database/sql/common_test.go b/database/sql/common_test.go new file mode 100644 index 00000000..af0adcf9 --- /dev/null +++ b/database/sql/common_test.go @@ -0,0 +1,7 @@ +package sql + +const ( + wrongPassphrase = "wrong-passphrase" + webhookSecret = "webhook-secret" + falseString = "false" +) diff --git a/database/sql/controller.go b/database/sql/controller.go index 7c2baf65..c4389cb1 100644 --- a/database/sql/controller.go +++ b/database/sql/controller.go @@ -15,12 +15,12 @@ package sql import ( - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - "github.com/cloudbase/garm/params" - "github.com/google/uuid" "github.com/pkg/errors" "gorm.io/gorm" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm/params" ) func (s *sqlDatabase) ControllerInfo() (params.ControllerInfo, error) { diff --git a/database/sql/controller_test.go b/database/sql/controller_test.go index 7f82160c..b4076e92 100644 --- a/database/sql/controller_test.go +++ b/database/sql/controller_test.go @@ -19,11 +19,11 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/suite" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" dbCommon "github.com/cloudbase/garm/database/common" - garmTesting "github.com/cloudbase/garm/internal/testing" - - "github.com/stretchr/testify/suite" + garmTesting "github.com/cloudbase/garm/internal/testing" //nolint:typecheck ) type CtrlTestSuite struct { diff --git a/database/sql/enterprise.go b/database/sql/enterprise.go index 59ead107..5133b255 100644 --- a/database/sql/enterprise.go +++ b/database/sql/enterprise.go @@ -3,17 +3,17 @@ package sql import ( "context" - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - "github.com/cloudbase/garm-provider-common/util" - "github.com/cloudbase/garm/params" - "github.com/google/uuid" "github.com/pkg/errors" "gorm.io/datatypes" "gorm.io/gorm" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm-provider-common/util" + "github.com/cloudbase/garm/params" ) -func (s *sqlDatabase) CreateEnterprise(ctx context.Context, name, credentialsName, webhookSecret string) (params.Enterprise, error) { +func (s *sqlDatabase) CreateEnterprise(_ context.Context, name, credentialsName, webhookSecret string) (params.Enterprise, error) { if webhookSecret == "" { return params.Enterprise{}, errors.New("creating enterprise: missing secret") } @@ -66,7 +66,7 @@ func (s *sqlDatabase) GetEnterpriseByID(ctx context.Context, enterpriseID string return param, nil } -func (s *sqlDatabase) ListEnterprises(ctx context.Context) ([]params.Enterprise, error) { +func (s *sqlDatabase) ListEnterprises(_ context.Context) ([]params.Enterprise, error) { var enterprises []Enterprise q := s.conn.Find(&enterprises) if q.Error != nil { @@ -181,8 +181,8 @@ func (s *sqlDatabase) CreateEnterprisePool(ctx context.Context, enterpriseID str return params.Pool{}, errors.Wrap(q.Error, "adding pool") } - for _, tt := range tags { - if err := s.conn.Model(&newPool).Association("Tags").Append(&tt); err != nil { + for i := range tags { + if err := s.conn.Model(&newPool).Association("Tags").Append(&tags[i]); err != nil { return params.Pool{}, errors.Wrap(err, "saving tag") } } @@ -224,7 +224,7 @@ func (s *sqlDatabase) UpdateEnterprisePool(ctx context.Context, enterpriseID, po return s.updatePool(pool, param) } -func (s *sqlDatabase) FindEnterprisePoolByTags(ctx context.Context, enterpriseID string, tags []string) (params.Pool, error) { +func (s *sqlDatabase) FindEnterprisePoolByTags(_ context.Context, enterpriseID string, tags []string) (params.Pool, error) { pool, err := s.findPoolByTags(enterpriseID, params.EnterprisePool, tags) if err != nil { return params.Pool{}, errors.Wrap(err, "fetching pool") @@ -267,7 +267,7 @@ func (s *sqlDatabase) ListEnterpriseInstances(ctx context.Context, enterpriseID return ret, nil } -func (s *sqlDatabase) getEnterprise(ctx context.Context, name string) (Enterprise, error) { +func (s *sqlDatabase) getEnterprise(_ context.Context, name string) (Enterprise, error) { var enterprise Enterprise q := s.conn.Where("name = ? COLLATE NOCASE", name) @@ -281,7 +281,7 @@ func (s *sqlDatabase) getEnterprise(ctx context.Context, name string) (Enterpris return enterprise, nil } -func (s *sqlDatabase) getEnterpriseByID(ctx context.Context, id string, preload ...string) (Enterprise, error) { +func (s *sqlDatabase) getEnterpriseByID(_ context.Context, id string, preload ...string) (Enterprise, error) { u, err := uuid.Parse(id) if err != nil { return Enterprise{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id") diff --git a/database/sql/enterprise_test.go b/database/sql/enterprise_test.go index 91e45898..e00af874 100644 --- a/database/sql/enterprise_test.go +++ b/database/sql/enterprise_test.go @@ -22,17 +22,16 @@ import ( "sort" "testing" - "github.com/cloudbase/garm/params" - - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - dbCommon "github.com/cloudbase/garm/database/common" - garmTesting "github.com/cloudbase/garm/internal/testing" - "github.com/stretchr/testify/suite" "gopkg.in/DATA-DOG/go-sqlmock.v1" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + dbCommon "github.com/cloudbase/garm/database/common" + garmTesting "github.com/cloudbase/garm/internal/testing" + "github.com/cloudbase/garm/params" ) type EnterpriseTestFixtures struct { @@ -105,7 +104,7 @@ func (s *EnterpriseTestSuite) SetupTest() { SkipInitializeWithVersion: true, } gormConfig := &gorm.Config{} - if flag.Lookup("test.v").Value.String() == "false" { + if flag.Lookup("test.v").Value.String() == falseString { gormConfig.Logger = logger.Default.LogMode(logger.Silent) } gormConn, err := gorm.Open(mysql.New(mysqlConfig), gormConfig) @@ -183,7 +182,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterpriseInvalidDBPassphrase() { s.FailNow(fmt.Sprintf("failed to create db connection: %s", err)) } // make sure we use a 'sqlDatabase' struct with a wrong 'cfg.Passphrase' - cfg.Passphrase = "wrong-passphrase" // it must have a size different than 32 + cfg.Passphrase = wrongPassphrase // it must have a size different than 32 sqlDB := &sqlDatabase{ conn: conn, cfg: cfg, @@ -322,7 +321,7 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseInvalidEnterpriseID() { } func (s *EnterpriseTestSuite) TestUpdateEnterpriseDBEncryptErr() { - s.StoreSQLMocked.cfg.Passphrase = "wrong-passphrase" + s.StoreSQLMocked.cfg.Passphrase = wrongPassphrase s.Fixtures.SQLMock. ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")). @@ -355,8 +354,8 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseDBSaveErr() { } func (s *EnterpriseTestSuite) TestUpdateEnterpriseDBDecryptingErr() { - s.StoreSQLMocked.cfg.Passphrase = "wrong-passphrase" - s.Fixtures.UpdateRepoParams.WebhookSecret = "webhook-secret" + s.StoreSQLMocked.cfg.Passphrase = wrongPassphrase + s.Fixtures.UpdateRepoParams.WebhookSecret = webhookSecret s.Fixtures.SQLMock. ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")). diff --git a/database/sql/instances.go b/database/sql/instances.go index 608d4fa6..4233f295 100644 --- a/database/sql/instances.go +++ b/database/sql/instances.go @@ -18,15 +18,15 @@ import ( "context" "encoding/json" - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - "github.com/cloudbase/garm-provider-common/util" - "github.com/cloudbase/garm/params" - "github.com/google/uuid" "github.com/pkg/errors" "gorm.io/datatypes" "gorm.io/gorm" "gorm.io/gorm/clause" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm-provider-common/util" + "github.com/cloudbase/garm/params" ) func (s *sqlDatabase) marshalAndSeal(data interface{}) ([]byte, error) { @@ -92,7 +92,7 @@ func (s *sqlDatabase) CreateInstance(ctx context.Context, poolID string, param p return s.sqlToParamsInstance(newInstance) } -func (s *sqlDatabase) getInstanceByID(ctx context.Context, instanceID string) (Instance, error) { +func (s *sqlDatabase) getInstanceByID(_ context.Context, instanceID string) (Instance, error) { u, err := uuid.Parse(instanceID) if err != nil { return Instance{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id") @@ -128,7 +128,7 @@ func (s *sqlDatabase) getPoolInstanceByName(ctx context.Context, poolID string, return instance, nil } -func (s *sqlDatabase) getInstanceByName(ctx context.Context, instanceName string, preload ...string) (Instance, error) { +func (s *sqlDatabase) getInstanceByName(_ context.Context, instanceName string, preload ...string) (Instance, error) { var instance Instance q := s.conn @@ -184,7 +184,7 @@ func (s *sqlDatabase) DeleteInstance(ctx context.Context, poolID string, instanc return nil } -func (s *sqlDatabase) ListInstanceEvents(ctx context.Context, instanceID string, eventType params.EventType, eventLevel params.EventLevel) ([]params.StatusMessage, error) { +func (s *sqlDatabase) ListInstanceEvents(_ context.Context, instanceID string, eventType params.EventType, eventLevel params.EventLevel) ([]params.StatusMessage, error) { var events []InstanceStatusUpdate query := s.conn.Model(&InstanceStatusUpdate{}).Where("instance_id = ?", instanceID) if eventLevel != "" { @@ -296,7 +296,7 @@ func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceID string, par return s.sqlToParamsInstance(instance) } -func (s *sqlDatabase) ListPoolInstances(ctx context.Context, poolID string) ([]params.Instance, error) { +func (s *sqlDatabase) ListPoolInstances(_ context.Context, poolID string) ([]params.Instance, error) { u, err := uuid.Parse(poolID) if err != nil { return nil, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id") @@ -319,7 +319,7 @@ func (s *sqlDatabase) ListPoolInstances(ctx context.Context, poolID string) ([]p return ret, nil } -func (s *sqlDatabase) ListAllInstances(ctx context.Context) ([]params.Instance, error) { +func (s *sqlDatabase) ListAllInstances(_ context.Context) ([]params.Instance, error) { var instances []Instance q := s.conn.Model(&Instance{}).Find(&instances) diff --git a/database/sql/instances_test.go b/database/sql/instances_test.go index 18c58ab9..44fd95c3 100644 --- a/database/sql/instances_test.go +++ b/database/sql/instances_test.go @@ -22,18 +22,16 @@ import ( "sort" "testing" - commonParams "github.com/cloudbase/garm-provider-common/params" - - dbCommon "github.com/cloudbase/garm/database/common" - garmTesting "github.com/cloudbase/garm/internal/testing" - "github.com/cloudbase/garm/params" - - "gopkg.in/DATA-DOG/go-sqlmock.v1" - "github.com/stretchr/testify/suite" + "gopkg.in/DATA-DOG/go-sqlmock.v1" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" + + commonParams "github.com/cloudbase/garm-provider-common/params" + dbCommon "github.com/cloudbase/garm/database/common" + garmTesting "github.com/cloudbase/garm/internal/testing" + "github.com/cloudbase/garm/params" ) type InstancesTestFixtures struct { @@ -131,7 +129,7 @@ func (s *InstancesTestSuite) SetupTest() { SkipInitializeWithVersion: true, } gormConfig := &gorm.Config{} - if flag.Lookup("test.v").Value.String() == "false" { + if flag.Lookup("test.v").Value.String() == falseString { gormConfig.Logger = logger.Default.LogMode(logger.Silent) } gormConn, err := gorm.Open(mysql.New(mysqlConfig), gormConfig) diff --git a/database/sql/jobs.go b/database/sql/jobs.go index e0ed7ef8..0ab77e90 100644 --- a/database/sql/jobs.go +++ b/database/sql/jobs.go @@ -5,13 +5,14 @@ import ( "encoding/json" "log/slog" - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - "github.com/cloudbase/garm/database/common" - "github.com/cloudbase/garm/params" "github.com/google/uuid" "github.com/pkg/errors" "gorm.io/gorm" "gorm.io/gorm/clause" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm/database/common" + "github.com/cloudbase/garm/params" ) var _ common.JobsStore = &sqlDatabase{} @@ -54,7 +55,7 @@ func sqlWorkflowJobToParamsJob(job WorkflowJob) (params.Job, error) { } func (s *sqlDatabase) paramsJobToWorkflowJob(ctx context.Context, job params.Job) (WorkflowJob, error) { - asJson, err := json.Marshal(job.Labels) + asJSON, err := json.Marshal(job.Labels) if err != nil { return WorkflowJob{}, errors.Wrap(err, "marshaling labels") } @@ -76,7 +77,7 @@ func (s *sqlDatabase) paramsJobToWorkflowJob(ctx context.Context, job params.Job RepoID: job.RepoID, OrgID: job.OrgID, EnterpriseID: job.EnterpriseID, - Labels: asJson, + Labels: asJSON, LockedBy: job.LockedBy, } @@ -92,7 +93,7 @@ func (s *sqlDatabase) paramsJobToWorkflowJob(ctx context.Context, job params.Job return workflofJob, nil } -func (s *sqlDatabase) DeleteJob(ctx context.Context, jobID int64) error { +func (s *sqlDatabase) DeleteJob(_ context.Context, jobID int64) error { q := s.conn.Delete(&WorkflowJob{}, jobID) if q.Error != nil { if errors.Is(q.Error, gorm.ErrRecordNotFound) { @@ -103,7 +104,7 @@ func (s *sqlDatabase) DeleteJob(ctx context.Context, jobID int64) error { return nil } -func (s *sqlDatabase) LockJob(ctx context.Context, jobID int64, entityID string) error { +func (s *sqlDatabase) LockJob(_ context.Context, jobID int64, entityID string) error { entityUUID, err := uuid.Parse(entityID) if err != nil { return errors.Wrap(err, "parsing entity id") @@ -136,7 +137,7 @@ func (s *sqlDatabase) LockJob(ctx context.Context, jobID int64, entityID string) return nil } -func (s *sqlDatabase) BreakLockJobIsQueued(ctx context.Context, jobID int64) error { +func (s *sqlDatabase) BreakLockJobIsQueued(_ context.Context, jobID int64) error { var workflowJob WorkflowJob q := s.conn.Clauses(clause.Locking{Strength: "UPDATE"}).Preload("Instance").Where("id = ? and status = ?", jobID, params.JobStatusQueued).First(&workflowJob) @@ -160,7 +161,7 @@ func (s *sqlDatabase) BreakLockJobIsQueued(ctx context.Context, jobID int64) err return nil } -func (s *sqlDatabase) UnlockJob(ctx context.Context, jobID int64, entityID string) error { +func (s *sqlDatabase) UnlockJob(_ context.Context, jobID int64, entityID string) error { var workflowJob WorkflowJob q := s.conn.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ?", jobID).First(&workflowJob) @@ -250,7 +251,7 @@ func (s *sqlDatabase) CreateOrUpdateJob(ctx context.Context, job params.Job) (pa } // ListJobsByStatus lists all jobs for a given status. -func (s *sqlDatabase) ListJobsByStatus(ctx context.Context, status params.JobStatus) ([]params.Job, error) { +func (s *sqlDatabase) ListJobsByStatus(_ context.Context, status params.JobStatus) ([]params.Job, error) { var jobs []WorkflowJob query := s.conn.Model(&WorkflowJob{}).Preload("Instance").Where("status = ?", status) @@ -270,7 +271,7 @@ func (s *sqlDatabase) ListJobsByStatus(ctx context.Context, status params.JobSta } // ListEntityJobsByStatus lists all jobs for a given entity type and id. -func (s *sqlDatabase) ListEntityJobsByStatus(ctx context.Context, entityType params.PoolType, entityID string, status params.JobStatus) ([]params.Job, error) { +func (s *sqlDatabase) ListEntityJobsByStatus(_ context.Context, entityType params.PoolType, entityID string, status params.JobStatus) ([]params.Job, error) { u, err := uuid.Parse(entityID) if err != nil { return nil, err @@ -306,7 +307,7 @@ func (s *sqlDatabase) ListEntityJobsByStatus(ctx context.Context, entityType par return ret, nil } -func (s *sqlDatabase) ListAllJobs(ctx context.Context) ([]params.Job, error) { +func (s *sqlDatabase) ListAllJobs(_ context.Context) ([]params.Job, error) { var jobs []WorkflowJob query := s.conn.Model(&WorkflowJob{}) @@ -329,7 +330,7 @@ func (s *sqlDatabase) ListAllJobs(ctx context.Context) ([]params.Job, error) { } // GetJobByID gets a job by id. -func (s *sqlDatabase) GetJobByID(ctx context.Context, jobID int64) (params.Job, error) { +func (s *sqlDatabase) GetJobByID(_ context.Context, jobID int64) (params.Job, error) { var job WorkflowJob query := s.conn.Model(&WorkflowJob{}).Preload("Instance").Where("id = ?", jobID) @@ -344,7 +345,7 @@ func (s *sqlDatabase) GetJobByID(ctx context.Context, jobID int64) (params.Job, } // DeleteCompletedJobs deletes all completed jobs. -func (s *sqlDatabase) DeleteCompletedJobs(ctx context.Context) error { +func (s *sqlDatabase) DeleteCompletedJobs(_ context.Context) error { query := s.conn.Model(&WorkflowJob{}).Where("status = ?", params.JobStatusCompleted) if err := query.Unscoped().Delete(&WorkflowJob{}); err.Error != nil { diff --git a/database/sql/models.go b/database/sql/models.go index f33fe9c8..047d4195 100644 --- a/database/sql/models.go +++ b/database/sql/models.go @@ -17,13 +17,13 @@ package sql import ( "time" - commonParams "github.com/cloudbase/garm-provider-common/params" - "github.com/cloudbase/garm/params" - "github.com/google/uuid" "github.com/pkg/errors" "gorm.io/datatypes" "gorm.io/gorm" + + commonParams "github.com/cloudbase/garm-provider-common/params" + "github.com/cloudbase/garm/params" ) type Base struct { @@ -33,9 +33,9 @@ type Base struct { DeletedAt gorm.DeletedAt `gorm:"index"` } -func (b *Base) BeforeCreate(tx *gorm.DB) error { - emptyId := uuid.UUID{} - if b.ID != emptyId { +func (b *Base) BeforeCreate(_ *gorm.DB) error { + emptyID := uuid.UUID{} + if b.ID != emptyID { return nil } newID, err := uuid.NewRandom() diff --git a/database/sql/organizations.go b/database/sql/organizations.go index 135db539..214757cf 100644 --- a/database/sql/organizations.go +++ b/database/sql/organizations.go @@ -18,17 +18,17 @@ import ( "context" "fmt" - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - "github.com/cloudbase/garm-provider-common/util" - "github.com/cloudbase/garm/params" - "github.com/google/uuid" "github.com/pkg/errors" "gorm.io/datatypes" "gorm.io/gorm" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm-provider-common/util" + "github.com/cloudbase/garm/params" ) -func (s *sqlDatabase) CreateOrganization(ctx context.Context, name, credentialsName, webhookSecret string) (params.Organization, error) { +func (s *sqlDatabase) CreateOrganization(_ context.Context, name, credentialsName, webhookSecret string) (params.Organization, error) { if webhookSecret == "" { return params.Organization{}, errors.New("creating org: missing secret") } @@ -70,7 +70,7 @@ func (s *sqlDatabase) GetOrganization(ctx context.Context, name string) (params. return param, nil } -func (s *sqlDatabase) ListOrganizations(ctx context.Context) ([]params.Organization, error) { +func (s *sqlDatabase) ListOrganizations(_ context.Context) ([]params.Organization, error) { var orgs []Organization q := s.conn.Find(&orgs) if q.Error != nil { @@ -146,12 +146,12 @@ func (s *sqlDatabase) GetOrganizationByID(ctx context.Context, orgID string) (pa return param, nil } -func (s *sqlDatabase) CreateOrganizationPool(ctx context.Context, orgId string, param params.CreatePoolParams) (params.Pool, error) { +func (s *sqlDatabase) CreateOrganizationPool(ctx context.Context, orgID string, param params.CreatePoolParams) (params.Pool, error) { if len(param.Tags) == 0 { return params.Pool{}, runnerErrors.NewBadRequestError("no tags specified") } - org, err := s.getOrgByID(ctx, orgId) + org, err := s.getOrgByID(ctx, orgID) if err != nil { return params.Pool{}, errors.Wrap(err, "fetching org") } @@ -175,7 +175,7 @@ func (s *sqlDatabase) CreateOrganizationPool(ctx context.Context, orgId string, newPool.ExtraSpecs = datatypes.JSON(param.ExtraSpecs) } - _, err = s.getOrgPoolByUniqueFields(ctx, orgId, newPool.ProviderName, newPool.Image, newPool.Flavor) + _, err = s.getOrgPoolByUniqueFields(ctx, orgID, newPool.ProviderName, newPool.Image, newPool.Flavor) if err != nil { if !errors.Is(err, runnerErrors.ErrNotFound) { return params.Pool{}, errors.Wrap(err, "creating pool") @@ -198,8 +198,8 @@ func (s *sqlDatabase) CreateOrganizationPool(ctx context.Context, orgId string, return params.Pool{}, errors.Wrap(q.Error, "adding pool") } - for _, tt := range tags { - if err := s.conn.Model(&newPool).Association("Tags").Append(&tt); err != nil { + for i := range tags { + if err := s.conn.Model(&newPool).Association("Tags").Append(&tags[i]); err != nil { return params.Pool{}, errors.Wrap(err, "saving tag") } } @@ -249,7 +249,7 @@ func (s *sqlDatabase) DeleteOrganizationPool(ctx context.Context, orgID, poolID return nil } -func (s *sqlDatabase) FindOrganizationPoolByTags(ctx context.Context, orgID string, tags []string) (params.Pool, error) { +func (s *sqlDatabase) FindOrganizationPoolByTags(_ context.Context, orgID string, tags []string) (params.Pool, error) { pool, err := s.findPoolByTags(orgID, params.OrganizationPool, tags) if err != nil { return params.Pool{}, errors.Wrap(err, "fetching pool") @@ -284,7 +284,7 @@ func (s *sqlDatabase) UpdateOrganizationPool(ctx context.Context, orgID, poolID return s.updatePool(pool, param) } -func (s *sqlDatabase) getPoolByID(ctx context.Context, poolID string, preload ...string) (Pool, error) { +func (s *sqlDatabase) getPoolByID(_ context.Context, poolID string, preload ...string) (Pool, error) { u, err := uuid.Parse(poolID) if err != nil { return Pool{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id") @@ -308,7 +308,7 @@ func (s *sqlDatabase) getPoolByID(ctx context.Context, poolID string, preload .. return pool, nil } -func (s *sqlDatabase) getOrgByID(ctx context.Context, id string, preload ...string) (Organization, error) { +func (s *sqlDatabase) getOrgByID(_ context.Context, id string, preload ...string) (Organization, error) { u, err := uuid.Parse(id) if err != nil { return Organization{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id") @@ -332,7 +332,7 @@ func (s *sqlDatabase) getOrgByID(ctx context.Context, id string, preload ...stri return org, nil } -func (s *sqlDatabase) getOrg(ctx context.Context, name string) (Organization, error) { +func (s *sqlDatabase) getOrg(_ context.Context, name string) (Organization, error) { var org Organization q := s.conn.Where("name = ? COLLATE NOCASE", name) diff --git a/database/sql/organizations_test.go b/database/sql/organizations_test.go index b664fc8b..50e46191 100644 --- a/database/sql/organizations_test.go +++ b/database/sql/organizations_test.go @@ -22,16 +22,16 @@ import ( "sort" "testing" - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - dbCommon "github.com/cloudbase/garm/database/common" - garmTesting "github.com/cloudbase/garm/internal/testing" - "github.com/cloudbase/garm/params" - "github.com/stretchr/testify/suite" "gopkg.in/DATA-DOG/go-sqlmock.v1" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + dbCommon "github.com/cloudbase/garm/database/common" + garmTesting "github.com/cloudbase/garm/internal/testing" + "github.com/cloudbase/garm/params" ) type OrgTestFixtures struct { @@ -104,7 +104,7 @@ func (s *OrgTestSuite) SetupTest() { SkipInitializeWithVersion: true, } gormConfig := &gorm.Config{} - if flag.Lookup("test.v").Value.String() == "false" { + if flag.Lookup("test.v").Value.String() == falseString { gormConfig.Logger = logger.Default.LogMode(logger.Silent) } gormConn, err := gorm.Open(mysql.New(mysqlConfig), gormConfig) @@ -182,7 +182,7 @@ func (s *OrgTestSuite) TestCreateOrganizationInvalidDBPassphrase() { s.FailNow(fmt.Sprintf("failed to create db connection: %s", err)) } // make sure we use a 'sqlDatabase' struct with a wrong 'cfg.Passphrase' - cfg.Passphrase = "wrong-passphrase" // it must have a size different than 32 + cfg.Passphrase = wrongPassphrase // it must have a size different than 32 sqlDB := &sqlDatabase{ conn: conn, cfg: cfg, @@ -321,7 +321,7 @@ func (s *OrgTestSuite) TestUpdateOrganizationInvalidOrgID() { } func (s *OrgTestSuite) TestUpdateOrganizationDBEncryptErr() { - s.StoreSQLMocked.cfg.Passphrase = "wrong-passphrase" + s.StoreSQLMocked.cfg.Passphrase = wrongPassphrase s.Fixtures.SQLMock. ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")). @@ -354,8 +354,8 @@ func (s *OrgTestSuite) TestUpdateOrganizationDBSaveErr() { } func (s *OrgTestSuite) TestUpdateOrganizationDBDecryptingErr() { - s.StoreSQLMocked.cfg.Passphrase = "wrong-passphrase" - s.Fixtures.UpdateRepoParams.WebhookSecret = "webhook-secret" + s.StoreSQLMocked.cfg.Passphrase = wrongPassphrase + s.Fixtures.UpdateRepoParams.WebhookSecret = webhookSecret s.Fixtures.SQLMock. ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")). diff --git a/database/sql/pools.go b/database/sql/pools.go index aa3a7f14..9d6737e6 100644 --- a/database/sql/pools.go +++ b/database/sql/pools.go @@ -18,15 +18,21 @@ import ( "context" "fmt" - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - "github.com/cloudbase/garm/params" - "github.com/google/uuid" "github.com/pkg/errors" "gorm.io/gorm" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm/params" ) -func (s *sqlDatabase) ListAllPools(ctx context.Context) ([]params.Pool, error) { +const ( + entityTypeEnterpriseName = "enterprise_id" + entityTypeOrgName = "org_id" + entityTypeRepoName = "repo_id" +) + +func (s *sqlDatabase) ListAllPools(_ context.Context) ([]params.Pool, error) { var pools []Pool q := s.conn.Model(&Pool{}). @@ -72,7 +78,7 @@ func (s *sqlDatabase) DeletePoolByID(ctx context.Context, poolID string) error { return nil } -func (s *sqlDatabase) getEntityPool(ctx context.Context, entityType params.PoolType, entityID, poolID string, preload ...string) (Pool, error) { +func (s *sqlDatabase) getEntityPool(_ context.Context, entityType params.PoolType, entityID, poolID string, preload ...string) (Pool, error) { if entityID == "" { return Pool{}, errors.Wrap(runnerErrors.ErrBadRequest, "missing entity id") } @@ -92,11 +98,11 @@ func (s *sqlDatabase) getEntityPool(ctx context.Context, entityType params.PoolT var fieldName string switch entityType { case params.RepositoryPool: - fieldName = "repo_id" + fieldName = entityTypeRepoName case params.OrganizationPool: - fieldName = "org_id" + fieldName = entityTypeOrgName case params.EnterprisePool: - fieldName = "enterprise_id" + fieldName = entityTypeEnterpriseName default: return Pool{}, fmt.Errorf("invalid entityType: %v", entityType) } @@ -106,7 +112,6 @@ func (s *sqlDatabase) getEntityPool(ctx context.Context, entityType params.PoolT err = q.Model(&Pool{}). Where(condition, u, entityID). First(&pool).Error - if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return Pool{}, errors.Wrap(runnerErrors.ErrNotFound, "finding pool") @@ -117,7 +122,7 @@ func (s *sqlDatabase) getEntityPool(ctx context.Context, entityType params.PoolT return pool, nil } -func (s *sqlDatabase) listEntityPools(ctx context.Context, entityType params.PoolType, entityID string, preload ...string) ([]Pool, error) { +func (s *sqlDatabase) listEntityPools(_ context.Context, entityType params.PoolType, entityID string, preload ...string) ([]Pool, error) { if _, err := uuid.Parse(entityID); err != nil { return nil, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id") } @@ -132,11 +137,11 @@ func (s *sqlDatabase) listEntityPools(ctx context.Context, entityType params.Poo var fieldName string switch entityType { case params.RepositoryPool: - fieldName = "repo_id" + fieldName = entityTypeRepoName case params.OrganizationPool: - fieldName = "org_id" + fieldName = entityTypeOrgName case params.EnterprisePool: - fieldName = "enterprise_id" + fieldName = entityTypeEnterpriseName default: return nil, fmt.Errorf("invalid entityType: %v", entityType) } @@ -147,7 +152,6 @@ func (s *sqlDatabase) listEntityPools(ctx context.Context, entityType params.Poo Where(condition, entityID). Omit("extra_specs"). Find(&pools).Error - if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return []Pool{}, nil @@ -170,11 +174,11 @@ func (s *sqlDatabase) findPoolByTags(id string, poolType params.PoolType, tags [ var fieldName string switch poolType { case params.RepositoryPool: - fieldName = "repo_id" + fieldName = entityTypeRepoName case params.OrganizationPool: - fieldName = "org_id" + fieldName = entityTypeOrgName case params.EnterprisePool: - fieldName = "enterprise_id" + fieldName = entityTypeEnterpriseName default: return nil, fmt.Errorf("invalid poolType: %v", poolType) } @@ -210,7 +214,7 @@ func (s *sqlDatabase) findPoolByTags(id string, poolType params.PoolType, tags [ return ret, nil } -func (s *sqlDatabase) FindPoolsMatchingAllTags(ctx context.Context, entityType params.PoolType, entityID string, tags []string) ([]params.Pool, error) { +func (s *sqlDatabase) FindPoolsMatchingAllTags(_ context.Context, entityType params.PoolType, entityID string, tags []string) ([]params.Pool, error) { if len(tags) == 0 { return nil, runnerErrors.NewBadRequestError("missing tags") } diff --git a/database/sql/pools_test.go b/database/sql/pools_test.go index 277ff4c5..c9a26fe0 100644 --- a/database/sql/pools_test.go +++ b/database/sql/pools_test.go @@ -21,15 +21,15 @@ import ( "regexp" "testing" - dbCommon "github.com/cloudbase/garm/database/common" - garmTesting "github.com/cloudbase/garm/internal/testing" - "github.com/cloudbase/garm/params" - "github.com/stretchr/testify/suite" "gopkg.in/DATA-DOG/go-sqlmock.v1" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" + + dbCommon "github.com/cloudbase/garm/database/common" + garmTesting "github.com/cloudbase/garm/internal/testing" + "github.com/cloudbase/garm/params" ) type PoolsTestFixtures struct { @@ -99,7 +99,7 @@ func (s *PoolsTestSuite) SetupTest() { SkipInitializeWithVersion: true, } gormConfig := &gorm.Config{} - if flag.Lookup("test.v").Value.String() == "false" { + if flag.Lookup("test.v").Value.String() == falseString { gormConfig.Logger = logger.Default.LogMode(logger.Silent) } gormConn, err := gorm.Open(mysql.New(mysqlConfig), gormConfig) diff --git a/database/sql/repositories.go b/database/sql/repositories.go index 31cb79e9..27adff32 100644 --- a/database/sql/repositories.go +++ b/database/sql/repositories.go @@ -18,17 +18,17 @@ import ( "context" "fmt" - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - "github.com/cloudbase/garm-provider-common/util" - "github.com/cloudbase/garm/params" - "github.com/google/uuid" "github.com/pkg/errors" "gorm.io/datatypes" "gorm.io/gorm" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm-provider-common/util" + "github.com/cloudbase/garm/params" ) -func (s *sqlDatabase) CreateRepository(ctx context.Context, owner, name, credentialsName, webhookSecret string) (params.Repository, error) { +func (s *sqlDatabase) CreateRepository(_ context.Context, owner, name, credentialsName, webhookSecret string) (params.Repository, error) { if webhookSecret == "" { return params.Repository{}, errors.New("creating repo: missing secret") } @@ -70,7 +70,7 @@ func (s *sqlDatabase) GetRepository(ctx context.Context, owner, name string) (pa return param, nil } -func (s *sqlDatabase) ListRepositories(ctx context.Context) ([]params.Repository, error) { +func (s *sqlDatabase) ListRepositories(_ context.Context) ([]params.Repository, error) { var repos []Repository q := s.conn.Find(&repos) if q.Error != nil { @@ -146,12 +146,12 @@ func (s *sqlDatabase) GetRepositoryByID(ctx context.Context, repoID string) (par return param, nil } -func (s *sqlDatabase) CreateRepositoryPool(ctx context.Context, repoId string, param params.CreatePoolParams) (params.Pool, error) { +func (s *sqlDatabase) CreateRepositoryPool(ctx context.Context, repoID string, param params.CreatePoolParams) (params.Pool, error) { if len(param.Tags) == 0 { return params.Pool{}, runnerErrors.NewBadRequestError("no tags specified") } - repo, err := s.getRepoByID(ctx, repoId) + repo, err := s.getRepoByID(ctx, repoID) if err != nil { return params.Pool{}, errors.Wrap(err, "fetching repo") } @@ -175,7 +175,7 @@ func (s *sqlDatabase) CreateRepositoryPool(ctx context.Context, repoId string, p newPool.ExtraSpecs = datatypes.JSON(param.ExtraSpecs) } - _, err = s.getRepoPoolByUniqueFields(ctx, repoId, newPool.ProviderName, newPool.Image, newPool.Flavor) + _, err = s.getRepoPoolByUniqueFields(ctx, repoID, newPool.ProviderName, newPool.Image, newPool.Flavor) if err != nil { if !errors.Is(err, runnerErrors.ErrNotFound) { return params.Pool{}, errors.Wrap(err, "creating pool") @@ -198,8 +198,8 @@ func (s *sqlDatabase) CreateRepositoryPool(ctx context.Context, repoId string, p return params.Pool{}, errors.Wrap(q.Error, "adding pool") } - for _, tt := range tags { - if err := s.conn.Model(&newPool).Association("Tags").Append(&tt); err != nil { + for i := range tags { + if err := s.conn.Model(&newPool).Association("Tags").Append(&tags[i]); err != nil { return params.Pool{}, errors.Wrap(err, "saving tag") } } @@ -249,7 +249,7 @@ func (s *sqlDatabase) DeleteRepositoryPool(ctx context.Context, repoID, poolID s return nil } -func (s *sqlDatabase) FindRepositoryPoolByTags(ctx context.Context, repoID string, tags []string) (params.Pool, error) { +func (s *sqlDatabase) FindRepositoryPoolByTags(_ context.Context, repoID string, tags []string) (params.Pool, error) { pool, err := s.findPoolByTags(repoID, params.RepositoryPool, tags) if err != nil { return params.Pool{}, errors.Wrap(err, "fetching pool") @@ -285,7 +285,7 @@ func (s *sqlDatabase) UpdateRepositoryPool(ctx context.Context, repoID, poolID s return s.updatePool(pool, param) } -func (s *sqlDatabase) getRepo(ctx context.Context, owner, name string) (Repository, error) { +func (s *sqlDatabase) getRepo(_ context.Context, owner, name string) (Repository, error) { var repo Repository q := s.conn.Where("name = ? COLLATE NOCASE and owner = ? COLLATE NOCASE", name, owner). @@ -321,7 +321,7 @@ func (s *sqlDatabase) getRepoPoolByUniqueFields(ctx context.Context, repoID stri return pool[0], nil } -func (s *sqlDatabase) getRepoByID(ctx context.Context, id string, preload ...string) (Repository, error) { +func (s *sqlDatabase) getRepoByID(_ context.Context, id string, preload ...string) (Repository, error) { u, err := uuid.Parse(id) if err != nil { return Repository{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id") diff --git a/database/sql/repositories_test.go b/database/sql/repositories_test.go index d87cc37b..7f3903b0 100644 --- a/database/sql/repositories_test.go +++ b/database/sql/repositories_test.go @@ -22,15 +22,15 @@ import ( "sort" "testing" - dbCommon "github.com/cloudbase/garm/database/common" - garmTesting "github.com/cloudbase/garm/internal/testing" - "github.com/cloudbase/garm/params" - "github.com/stretchr/testify/suite" "gopkg.in/DATA-DOG/go-sqlmock.v1" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" + + dbCommon "github.com/cloudbase/garm/database/common" + garmTesting "github.com/cloudbase/garm/internal/testing" + "github.com/cloudbase/garm/params" ) type RepoTestFixtures struct { @@ -115,7 +115,7 @@ func (s *RepoTestSuite) SetupTest() { SkipInitializeWithVersion: true, } gormConfig := &gorm.Config{} - if flag.Lookup("test.v").Value.String() == "false" { + if flag.Lookup("test.v").Value.String() == falseString { gormConfig.Logger = logger.Default.LogMode(logger.Silent) } gormConn, err := gorm.Open(mysql.New(mysqlConfig), gormConfig) @@ -197,7 +197,7 @@ func (s *RepoTestSuite) TestCreateRepositoryInvalidDBPassphrase() { s.FailNow(fmt.Sprintf("failed to create db connection: %s", err)) } // make sure we use a 'sqlDatabase' struct with a wrong 'cfg.Passphrase' - cfg.Passphrase = "wrong-passphrase" // it must have a size different than 32 + cfg.Passphrase = wrongPassphrase // it must have a size different than 32 sqlDB := &sqlDatabase{ conn: conn, cfg: cfg, @@ -296,7 +296,7 @@ func (s *RepoTestSuite) TestListRepositoriesDBFetchErr() { } func (s *RepoTestSuite) TestListRepositoriesDBDecryptingErr() { - s.StoreSQLMocked.cfg.Passphrase = "wrong-passphrase" + s.StoreSQLMocked.cfg.Passphrase = wrongPassphrase s.Fixtures.SQLMock. ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE `repositories`.`deleted_at` IS NULL")). @@ -360,7 +360,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryInvalidRepoID() { } func (s *RepoTestSuite) TestUpdateRepositoryDBEncryptErr() { - s.StoreSQLMocked.cfg.Passphrase = "wrong-passphrase" + s.StoreSQLMocked.cfg.Passphrase = wrongPassphrase s.Fixtures.SQLMock. ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")). @@ -392,8 +392,8 @@ func (s *RepoTestSuite) TestUpdateRepositoryDBSaveErr() { } func (s *RepoTestSuite) TestUpdateRepositoryDBDecryptingErr() { - s.StoreSQLMocked.cfg.Passphrase = "wrong-passphrase" - s.Fixtures.UpdateRepoParams.WebhookSecret = "webhook-secret" + s.StoreSQLMocked.cfg.Passphrase = wrongPassphrase + s.Fixtures.UpdateRepoParams.WebhookSecret = webhookSecret s.Fixtures.SQLMock. ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")). diff --git a/database/sql/users.go b/database/sql/users.go index 78922b80..039d86fe 100644 --- a/database/sql/users.go +++ b/database/sql/users.go @@ -18,12 +18,12 @@ import ( "context" "fmt" + "github.com/pkg/errors" + "gorm.io/gorm" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm-provider-common/util" "github.com/cloudbase/garm/params" - - "github.com/pkg/errors" - "gorm.io/gorm" ) func (s *sqlDatabase) getUserByUsernameOrEmail(user string) (User, error) { @@ -56,7 +56,7 @@ func (s *sqlDatabase) getUserByID(userID string) (User, error) { return dbUser, nil } -func (s *sqlDatabase) CreateUser(ctx context.Context, user params.NewUserParams) (params.User, error) { +func (s *sqlDatabase) CreateUser(_ context.Context, user params.NewUserParams) (params.User, error) { if user.Username == "" || user.Email == "" { return params.User{}, runnerErrors.NewBadRequestError("missing username or email") } @@ -83,13 +83,13 @@ func (s *sqlDatabase) CreateUser(ctx context.Context, user params.NewUserParams) return s.sqlToParamsUser(newUser), nil } -func (s *sqlDatabase) HasAdminUser(ctx context.Context) bool { +func (s *sqlDatabase) HasAdminUser(_ context.Context) bool { var user User q := s.conn.Model(&User{}).Where("is_admin = ?", true).First(&user) return q.Error == nil } -func (s *sqlDatabase) GetUser(ctx context.Context, user string) (params.User, error) { +func (s *sqlDatabase) GetUser(_ context.Context, user string) (params.User, error) { dbUser, err := s.getUserByUsernameOrEmail(user) if err != nil { return params.User{}, errors.Wrap(err, "fetching user") @@ -97,7 +97,7 @@ func (s *sqlDatabase) GetUser(ctx context.Context, user string) (params.User, er return s.sqlToParamsUser(dbUser), nil } -func (s *sqlDatabase) GetUserByID(ctx context.Context, userID string) (params.User, error) { +func (s *sqlDatabase) GetUserByID(_ context.Context, userID string) (params.User, error) { dbUser, err := s.getUserByID(userID) if err != nil { return params.User{}, errors.Wrap(err, "fetching user") @@ -105,7 +105,7 @@ func (s *sqlDatabase) GetUserByID(ctx context.Context, userID string) (params.Us return s.sqlToParamsUser(dbUser), nil } -func (s *sqlDatabase) UpdateUser(ctx context.Context, user string, param params.UpdateUserParams) (params.User, error) { +func (s *sqlDatabase) UpdateUser(_ context.Context, user string, param params.UpdateUserParams) (params.User, error) { dbUser, err := s.getUserByUsernameOrEmail(user) if err != nil { return params.User{}, errors.Wrap(err, "fetching user") diff --git a/database/sql/users_test.go b/database/sql/users_test.go index 37105cb6..1317130a 100644 --- a/database/sql/users_test.go +++ b/database/sql/users_test.go @@ -21,14 +21,15 @@ import ( "regexp" "testing" - dbCommon "github.com/cloudbase/garm/database/common" - garmTesting "github.com/cloudbase/garm/internal/testing" - "github.com/cloudbase/garm/params" "github.com/stretchr/testify/suite" "gopkg.in/DATA-DOG/go-sqlmock.v1" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" + + dbCommon "github.com/cloudbase/garm/database/common" + garmTesting "github.com/cloudbase/garm/internal/testing" + "github.com/cloudbase/garm/params" ) type UserTestFixtures struct { @@ -90,7 +91,7 @@ func (s *UserTestSuite) SetupTest() { SkipInitializeWithVersion: true, } gormConfig := &gorm.Config{} - if flag.Lookup("test.v").Value.String() == "false" { + if flag.Lookup("test.v").Value.String() == falseString { gormConfig.Logger = logger.Default.LogMode(logger.Silent) } gormConn, err := gorm.Open(mysql.New(mysqlConfig), gormConfig) diff --git a/database/sql/util.go b/database/sql/util.go index ad0a4d8b..dd3a956b 100644 --- a/database/sql/util.go +++ b/database/sql/util.go @@ -18,14 +18,13 @@ import ( "encoding/json" "fmt" - "github.com/cloudbase/garm-provider-common/util" - "github.com/cloudbase/garm/params" - "github.com/pkg/errors" "gorm.io/datatypes" "gorm.io/gorm" commonParams "github.com/cloudbase/garm-provider-common/params" + "github.com/cloudbase/garm-provider-common/util" + "github.com/cloudbase/garm/params" ) func (s *sqlDatabase) sqlToParamsInstance(instance Instance) (params.Instance, error) { diff --git a/internal/testing/testing.go b/internal/testing/testing.go index 754a799a..5f8624e6 100644 --- a/internal/testing/testing.go +++ b/internal/testing/testing.go @@ -23,14 +23,13 @@ import ( "sort" "testing" - "github.com/cloudbase/garm/config" - "github.com/stretchr/testify/require" + + "github.com/cloudbase/garm/config" ) -var ( - encryptionPassphrase = "bocyasicgatEtenOubwonIbsudNutDom" -) +//nolint:golangci-lint,gosec +var encryptionPassphrase = "bocyasicgatEtenOubwonIbsudNutDom" func GetTestSqliteDBConfig(t *testing.T) config.Database { dir, err := os.MkdirTemp("", "garm-config-test") diff --git a/metrics/health.go b/metrics/health.go index d1f5e969..4acfbb36 100644 --- a/metrics/health.go +++ b/metrics/health.go @@ -4,10 +4,8 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -var ( - GarmHealth = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: metricsNamespace, - Name: "health", - Help: "Health of the garm", - }, []string{"metadata_url", "callback_url", "webhook_url", "controller_webhook_url", "controller_id"}) -) +var GarmHealth = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: metricsNamespace, + Name: "health", + Help: "Health of the garm", +}, []string{"metadata_url", "callback_url", "webhook_url", "controller_webhook_url", "controller_id"}) diff --git a/metrics/metrics.go b/metrics/metrics.go index 44b75031..edceb30a 100644 --- a/metrics/metrics.go +++ b/metrics/metrics.go @@ -4,15 +4,17 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -const metricsNamespace = "garm" -const metricsRunnerSubsystem = "runner" -const metricsPoolSubsystem = "pool" -const metricsProviderSubsystem = "provider" -const metricsOrganizationSubsystem = "organization" -const metricsRepositorySubsystem = "repository" -const metricsEnterpriseSubsystem = "enterprise" -const metricsWebhookSubsystem = "webhook" -const metricsGithubSubsystem = "github" +const ( + metricsNamespace = "garm" + metricsRunnerSubsystem = "runner" + metricsPoolSubsystem = "pool" + metricsProviderSubsystem = "provider" + metricsOrganizationSubsystem = "organization" + metricsRepositorySubsystem = "repository" + metricsEnterpriseSubsystem = "enterprise" + metricsWebhookSubsystem = "webhook" + metricsGithubSubsystem = "github" +) // RegisterMetrics registers all the metrics func RegisterMetrics() error { diff --git a/metrics/provider.go b/metrics/provider.go index 5034a7e9..8285ca1e 100644 --- a/metrics/provider.go +++ b/metrics/provider.go @@ -4,11 +4,9 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -var ( - ProviderInfo = prometheus.NewGaugeVec(prometheus.GaugeOpts{ - Namespace: metricsNamespace, - Subsystem: metricsProviderSubsystem, - Name: "info", - Help: "Info of the organization", - }, []string{"name", "type", "description"}) -) +var ProviderInfo = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: metricsNamespace, + Subsystem: metricsProviderSubsystem, + Name: "info", + Help: "Info of the organization", +}, []string{"name", "type", "description"}) diff --git a/metrics/webhooks.go b/metrics/webhooks.go index 14b6492c..839219a4 100644 --- a/metrics/webhooks.go +++ b/metrics/webhooks.go @@ -2,11 +2,9 @@ package metrics import "github.com/prometheus/client_golang/prometheus" -var ( - WebhooksReceived = prometheus.NewCounterVec(prometheus.CounterOpts{ - Namespace: metricsNamespace, - Subsystem: metricsWebhookSubsystem, - Name: "received", - Help: "The total number of webhooks received", - }, []string{"valid", "reason"}) -) +var WebhooksReceived = prometheus.NewCounterVec(prometheus.CounterOpts{ + Namespace: metricsNamespace, + Subsystem: metricsWebhookSubsystem, + Name: "received", + Help: "The total number of webhooks received", +}, []string{"valid", "reason"}) diff --git a/params/params.go b/params/params.go index df37ddb2..8aa028cf 100644 --- a/params/params.go +++ b/params/params.go @@ -22,12 +22,11 @@ import ( "fmt" "time" - commonParams "github.com/cloudbase/garm-provider-common/params" - - "github.com/cloudbase/garm/util/appdefaults" - "github.com/google/go-github/v57/github" "github.com/google/uuid" + + commonParams "github.com/cloudbase/garm-provider-common/params" + "github.com/cloudbase/garm/util/appdefaults" ) type ( @@ -287,11 +286,12 @@ func (p *Pool) RunnerTimeout() uint { } func (p *Pool) PoolType() PoolType { - if p.RepoID != "" { + switch { + case p.RepoID != "": return RepositoryPool - } else if p.OrgID != "" { + case p.OrgID != "": return OrganizationPool - } else if p.EnterpriseID != "" { + case p.EnterpriseID != "": return EnterprisePool } return "" @@ -437,7 +437,7 @@ func (g GithubCredentials) RootCertificateBundle() (CertificateBundle, error) { ret := map[string][]byte{} var block *pem.Block - var rest []byte = g.CABundle + rest := g.CABundle for { block, rest = pem.Decode(rest) if block == nil { diff --git a/params/requests.go b/params/requests.go index 946c8536..2ad4fc1e 100644 --- a/params/requests.go +++ b/params/requests.go @@ -18,9 +18,8 @@ import ( "encoding/json" "fmt" - commonParams "github.com/cloudbase/garm-provider-common/params" - "github.com/cloudbase/garm-provider-common/errors" + commonParams "github.com/cloudbase/garm-provider-common/params" ) const DefaultRunnerPrefix = "garm" diff --git a/runner/common/mocks/Provider.go b/runner/common/mocks/Provider.go index 4c9d5727..7865995b 100644 --- a/runner/common/mocks/Provider.go +++ b/runner/common/mocks/Provider.go @@ -161,12 +161,12 @@ func (_m *Provider) Start(ctx context.Context, instance string) error { } // Stop provides a mock function with given fields: ctx, instance, force -func (_m *Provider) Stop(ctx context.Context, instance string, force bool) error { - ret := _m.Called(ctx, instance, force) +func (_m *Provider) Stop(ctx context.Context, instance string) error { + ret := _m.Called(ctx, instance) var r0 error - if rf, ok := ret.Get(0).(func(context.Context, string, bool) error); ok { - r0 = rf(ctx, instance, force) + if rf, ok := ret.Get(0).(func(context.Context, string) error); ok { + r0 = rf(ctx, instance) } else { r0 = ret.Error(0) } diff --git a/runner/common/pool.go b/runner/common/pool.go index 47655414..92696291 100644 --- a/runner/common/pool.go +++ b/runner/common/pool.go @@ -61,7 +61,7 @@ type PoolManager interface { ForceDeleteRunner(runner params.Instance) error // DeleteRunner will attempt to remove a runner from the pool. If forceRemove is true, any error - // received from the provider will be ignored and we will procede to remove the runner from the database. + // received from the provider will be ignored and we will proceed to remove the runner from the database. // An error received while attempting to remove from GitHub (other than 404) will still stop the deletion // process. This can happen if the runner is already processing a job. At which point, you can simply cancel // the job in github. Doing so will prompt GARM to reap the runner automatically. diff --git a/runner/common/provider.go b/runner/common/provider.go index 3a45bba9..8ed98e0c 100644 --- a/runner/common/provider.go +++ b/runner/common/provider.go @@ -34,7 +34,7 @@ type Provider interface { // RemoveAllInstances will remove all instances created by this provider. RemoveAllInstances(ctx context.Context) error // Stop shuts down the instance. - Stop(ctx context.Context, instance string, force bool) error + Stop(ctx context.Context, instance string) error // Start boots up an instance. Start(ctx context.Context, instance string) error // DisableJITConfig tells us if the provider explicitly disables JIT configuration and diff --git a/runner/common_test.go b/runner/common_test.go new file mode 100644 index 00000000..b9b53545 --- /dev/null +++ b/runner/common_test.go @@ -0,0 +1,9 @@ +package runner + +const ( + // nolint: gosec + notExistingCredentialsName = "not-existent-creds-name" + // nolint: gosec + invalidCredentialsName = "invalid-creds-name" + notExistingProviderName = "not-existent-provider-name" +) diff --git a/runner/enterprises.go b/runner/enterprises.go index cf2ca46e..84278a60 100644 --- a/runner/enterprises.go +++ b/runner/enterprises.go @@ -6,13 +6,13 @@ import ( "log/slog" "strings" + "github.com/pkg/errors" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" "github.com/cloudbase/garm/util/appdefaults" - - "github.com/pkg/errors" ) func (r *Runner) CreateEnterprise(ctx context.Context, param params.CreateEnterpriseParams) (enterprise params.Enterprise, err error) { @@ -130,12 +130,12 @@ func (r *Runner) DeleteEnterprise(ctx context.Context, enterpriseID string) erro } if len(pools) > 0 { - poolIds := []string{} + poolIDs := []string{} for _, pool := range pools { - poolIds = append(poolIds, pool.ID) + poolIDs = append(poolIDs, pool.ID) } - return runnerErrors.NewBadRequestError("enterprise has pools defined (%s)", strings.Join(poolIds, ", ")) + return runnerErrors.NewBadRequestError("enterprise has pools defined (%s)", strings.Join(poolIDs, ", ")) } if err := r.poolManagerCtrl.DeleteEnterprisePoolManager(enterprise); err != nil { @@ -233,6 +233,7 @@ func (r *Runner) DeleteEnterprisePool(ctx context.Context, enterpriseID, poolID return runnerErrors.ErrUnauthorized } + // nolint:golangci-lint,godox // TODO: dedup instance count verification pool, err := r.store.GetEnterprisePool(ctx, enterpriseID, poolID) if err != nil { @@ -244,6 +245,7 @@ func (r *Runner) DeleteEnterprisePool(ctx context.Context, enterpriseID, poolID return errors.Wrap(err, "fetching instances") } + // nolint:golangci-lint,godox // TODO: implement a count function if len(instances) > 0 { runnerIDs := []string{} diff --git a/runner/enterprises_test.go b/runner/enterprises_test.go index 922f1bff..5af95d96 100644 --- a/runner/enterprises_test.go +++ b/runner/enterprises_test.go @@ -19,19 +19,19 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/config" "github.com/cloudbase/garm/database" dbCommon "github.com/cloudbase/garm/database/common" - garmTesting "github.com/cloudbase/garm/internal/testing" + garmTesting "github.com/cloudbase/garm/internal/testing" //nolint:typecheck "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" runnerCommonMocks "github.com/cloudbase/garm/runner/common/mocks" runnerMocks "github.com/cloudbase/garm/runner/mocks" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" ) type EnterpriseTestFixtures struct { @@ -184,7 +184,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterpriseEmptyParams() { } func (s *EnterpriseTestSuite) TestCreateEnterpriseMissingCredentials() { - s.Fixtures.CreateEnterpriseParams.CredentialsName = "not-existent-creds-name" + s.Fixtures.CreateEnterpriseParams.CredentialsName = notExistingCredentialsName _, err := s.Runner.CreateEnterprise(s.Fixtures.AdminContext, s.Fixtures.CreateEnterpriseParams) @@ -309,7 +309,7 @@ func (s *EnterpriseTestSuite) TestUpdateEnterpriseErrUnauthorized() { } func (s *EnterpriseTestSuite) TestUpdateEnterpriseInvalidCreds() { - s.Fixtures.UpdateRepoParams.CredentialsName = "invalid-creds-name" + s.Fixtures.UpdateRepoParams.CredentialsName = invalidCredentialsName _, err := s.Runner.UpdateEnterprise(s.Fixtures.AdminContext, s.Fixtures.StoreEnterprises["test-enterprise-1"].ID, s.Fixtures.UpdateRepoParams) @@ -371,7 +371,7 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolErrNotFound() { } func (s *EnterpriseTestSuite) TestCreateEnterprisePoolFetchPoolParamsFailed() { - s.Fixtures.CreatePoolParams.ProviderName = "not-existent-provider-name" + s.Fixtures.CreatePoolParams.ProviderName = notExistingProviderName s.Fixtures.PoolMgrCtrlMock.On("GetEnterprisePoolManager", mock.AnythingOfType("params.Enterprise")).Return(s.Fixtures.PoolMgrMock, nil) diff --git a/runner/metadata.go b/runner/metadata.go index 7890434e..84151fcd 100644 --- a/runner/metadata.go +++ b/runner/metadata.go @@ -9,11 +9,12 @@ import ( "log/slog" "strings" + "github.com/pkg/errors" + "github.com/cloudbase/garm-provider-common/defaults" runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/params" - "github.com/pkg/errors" ) var systemdUnitTemplate = `[Unit] @@ -73,7 +74,7 @@ func (r *Runner) GetRunnerServiceName(ctx context.Context) (string, error) { case params.OrganizationPool: serviceName = fmt.Sprintf(tpl, pool.OrgName, instance.Name) case params.RepositoryPool: - serviceName = fmt.Sprintf(tpl, strings.Replace(pool.RepoName, "/", "-", -1), instance.Name) + serviceName = fmt.Sprintf(tpl, strings.ReplaceAll(pool.RepoName, "/", "-"), instance.Name) } return serviceName, nil } diff --git a/runner/metrics/enterprise.go b/runner/metrics/enterprise.go index 8cce89d6..407c0fc4 100644 --- a/runner/metrics/enterprise.go +++ b/runner/metrics/enterprise.go @@ -5,12 +5,11 @@ import ( "strconv" "github.com/cloudbase/garm/metrics" - "github.com/cloudbase/garm/runner" + "github.com/cloudbase/garm/runner" //nolint:typecheck ) // CollectOrganizationMetric collects the metrics for the enterprise objects func CollectEnterpriseMetric(ctx context.Context, r *runner.Runner) error { - // reset metrics metrics.EnterpriseInfo.Reset() metrics.EnterprisePoolManagerStatus.Reset() diff --git a/runner/metrics/health.go b/runner/metrics/health.go index d70adf10..05e1ed9b 100644 --- a/runner/metrics/health.go +++ b/runner/metrics/health.go @@ -1,14 +1,11 @@ package metrics import ( - "context" - "github.com/cloudbase/garm/metrics" "github.com/cloudbase/garm/params" - "github.com/cloudbase/garm/runner" ) -func CollectHealthMetric(ctx context.Context, r *runner.Runner, controllerInfo params.ControllerInfo) error { +func CollectHealthMetric(controllerInfo params.ControllerInfo) error { metrics.GarmHealth.WithLabelValues( controllerInfo.MetadataURL, // label: metadata_url controllerInfo.CallbackURL, // label: callback_url diff --git a/runner/metrics/instance.go b/runner/metrics/instance.go index a32fa081..06fd4881 100644 --- a/runner/metrics/instance.go +++ b/runner/metrics/instance.go @@ -10,7 +10,6 @@ import ( // CollectInstanceMetric collects the metrics for the runner instances // reflecting the statuses and the pool they belong to. func CollectInstanceMetric(ctx context.Context, r *runner.Runner) error { - // reset metrics metrics.InstanceStatus.Reset() @@ -32,29 +31,26 @@ func CollectInstanceMetric(ctx context.Context, r *runner.Runner) error { poolNames := make(map[string]poolInfo) for _, pool := range pools { - if pool.EnterpriseName != "" { + switch { + case pool.OrgName != "": poolNames[pool.ID] = poolInfo{ - Name: pool.EnterpriseName, - Type: string(pool.PoolType()), - ProviderName: pool.ProviderName, + Name: pool.OrgName, + Type: string(pool.PoolType()), } - } else if pool.OrgName != "" { + case pool.EnterpriseName != "": poolNames[pool.ID] = poolInfo{ - Name: pool.OrgName, - Type: string(pool.PoolType()), - ProviderName: pool.ProviderName, + Name: pool.EnterpriseName, + Type: string(pool.PoolType()), } - } else { + default: poolNames[pool.ID] = poolInfo{ - Name: pool.RepoName, - Type: string(pool.PoolType()), - ProviderName: pool.ProviderName, + Name: pool.RepoName, + Type: string(pool.PoolType()), } } } for _, instance := range instances { - metrics.InstanceStatus.WithLabelValues( instance.Name, // label: name string(instance.Status), // label: status diff --git a/runner/metrics/metrics.go b/runner/metrics/metrics.go index 59fc6bbb..24b01bab 100644 --- a/runner/metrics/metrics.go +++ b/runner/metrics/metrics.go @@ -82,7 +82,7 @@ func collectMetrics(ctx context.Context, r *runner.Runner, controllerInfo params } slog.DebugContext(ctx, "collecting health metrics") - err = CollectHealthMetric(ctx, r, controllerInfo) + err = CollectHealthMetric(controllerInfo) if err != nil { return err } diff --git a/runner/metrics/organization.go b/runner/metrics/organization.go index 0be9ced6..6b9f6b71 100644 --- a/runner/metrics/organization.go +++ b/runner/metrics/organization.go @@ -10,7 +10,6 @@ import ( // CollectOrganizationMetric collects the metrics for the organization objects func CollectOrganizationMetric(ctx context.Context, r *runner.Runner) error { - // reset metrics metrics.OrganizationInfo.Reset() metrics.OrganizationPoolManagerStatus.Reset() diff --git a/runner/metrics/pool.go b/runner/metrics/pool.go index 817cb104..44ad27a8 100644 --- a/runner/metrics/pool.go +++ b/runner/metrics/pool.go @@ -11,7 +11,6 @@ import ( // CollectPoolMetric collects the metrics for the pool objects func CollectPoolMetric(ctx context.Context, r *runner.Runner) error { - // reset metrics metrics.PoolInfo.Reset() metrics.PoolStatus.Reset() @@ -31,17 +30,18 @@ func CollectPoolMetric(ctx context.Context, r *runner.Runner) error { poolNames := make(map[string]poolInfo) for _, pool := range pools { - if pool.EnterpriseName != "" { - poolNames[pool.ID] = poolInfo{ - Name: pool.EnterpriseName, - Type: string(pool.PoolType()), - } - } else if pool.OrgName != "" { + switch { + case pool.OrgName != "": poolNames[pool.ID] = poolInfo{ Name: pool.OrgName, Type: string(pool.PoolType()), } - } else { + case pool.EnterpriseName != "": + poolNames[pool.ID] = poolInfo{ + Name: pool.EnterpriseName, + Type: string(pool.PoolType()), + } + default: poolNames[pool.ID] = poolInfo{ Name: pool.RepoName, Type: string(pool.PoolType()), diff --git a/runner/metrics/provider.go b/runner/metrics/provider.go index 398f8ee3..e2b38a9f 100644 --- a/runner/metrics/provider.go +++ b/runner/metrics/provider.go @@ -8,7 +8,6 @@ import ( ) func CollectProviderMetric(ctx context.Context, r *runner.Runner) error { - // reset metrics metrics.ProviderInfo.Reset() diff --git a/runner/metrics/repository.go b/runner/metrics/repository.go index ba2fab29..b76fcc0e 100644 --- a/runner/metrics/repository.go +++ b/runner/metrics/repository.go @@ -9,7 +9,6 @@ import ( ) func CollectRepositoryMetric(ctx context.Context, r *runner.Runner) error { - // reset metrics metrics.EnterpriseInfo.Reset() metrics.EnterprisePoolManagerStatus.Reset() diff --git a/runner/organizations.go b/runner/organizations.go index c86af1fb..ee863125 100644 --- a/runner/organizations.go +++ b/runner/organizations.go @@ -20,13 +20,13 @@ import ( "log/slog" "strings" + "github.com/pkg/errors" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" "github.com/cloudbase/garm/util/appdefaults" - - "github.com/pkg/errors" ) func (r *Runner) CreateOrganization(ctx context.Context, param params.CreateOrgParams) (org params.Organization, err error) { @@ -144,12 +144,12 @@ func (r *Runner) DeleteOrganization(ctx context.Context, orgID string, keepWebho } if len(pools) > 0 { - poolIds := []string{} + poolIDs := []string{} for _, pool := range pools { - poolIds = append(poolIds, pool.ID) + poolIDs = append(poolIDs, pool.ID) } - return runnerErrors.NewBadRequestError("org has pools defined (%s)", strings.Join(poolIds, ", ")) + return runnerErrors.NewBadRequestError("org has pools defined (%s)", strings.Join(poolIDs, ", ")) } if !keepWebhook && r.config.Default.EnableWebhookManagement { @@ -159,6 +159,7 @@ func (r *Runner) DeleteOrganization(ctx context.Context, orgID string, keepWebho } if err := poolMgr.UninstallWebhook(ctx); err != nil { + // nolint:golangci-lint,godox // TODO(gabriel-samfira): Should we error out here? slog.With(slog.Any("error", err)).ErrorContext( ctx, "failed to uninstall webhook", @@ -261,6 +262,7 @@ func (r *Runner) DeleteOrgPool(ctx context.Context, orgID, poolID string) error return runnerErrors.ErrUnauthorized } + // nolint:golangci-lint,godox // TODO: dedup instance count verification pool, err := r.store.GetOrganizationPool(ctx, orgID, poolID) if err != nil { @@ -272,6 +274,7 @@ func (r *Runner) DeleteOrgPool(ctx context.Context, orgID, poolID string) error return errors.Wrap(err, "fetching instances") } + // nolint:golangci-lint,godox // TODO: implement a count function if len(instances) > 0 { runnerIDs := []string{} diff --git a/runner/organizations_test.go b/runner/organizations_test.go index 167dbccf..e3a43fad 100644 --- a/runner/organizations_test.go +++ b/runner/organizations_test.go @@ -19,6 +19,9 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/config" @@ -29,9 +32,6 @@ import ( "github.com/cloudbase/garm/runner/common" runnerCommonMocks "github.com/cloudbase/garm/runner/common/mocks" runnerMocks "github.com/cloudbase/garm/runner/mocks" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" ) type OrgTestFixtures struct { @@ -184,7 +184,7 @@ func (s *OrgTestSuite) TestCreateOrganizationEmptyParams() { } func (s *OrgTestSuite) TestCreateOrganizationMissingCredentials() { - s.Fixtures.CreateOrgParams.CredentialsName = "not-existent-creds-name" + s.Fixtures.CreateOrgParams.CredentialsName = notExistingCredentialsName _, err := s.Runner.CreateOrganization(s.Fixtures.AdminContext, s.Fixtures.CreateOrgParams) @@ -309,7 +309,7 @@ func (s *OrgTestSuite) TestUpdateOrganizationErrUnauthorized() { } func (s *OrgTestSuite) TestUpdateOrganizationInvalidCreds() { - s.Fixtures.UpdateRepoParams.CredentialsName = "invalid-creds-name" + s.Fixtures.UpdateRepoParams.CredentialsName = invalidCredentialsName _, err := s.Runner.UpdateOrganization(s.Fixtures.AdminContext, s.Fixtures.StoreOrgs["test-org-1"].ID, s.Fixtures.UpdateRepoParams) @@ -371,7 +371,7 @@ func (s *OrgTestSuite) TestCreateOrgPoolErrNotFound() { } func (s *OrgTestSuite) TestCreateOrgPoolFetchPoolParamsFailed() { - s.Fixtures.CreatePoolParams.ProviderName = "not-existent-provider-name" + s.Fixtures.CreatePoolParams.ProviderName = notExistingProviderName s.Fixtures.PoolMgrCtrlMock.On("GetOrgPoolManager", mock.AnythingOfType("params.Organization")).Return(s.Fixtures.PoolMgrMock, nil) diff --git a/runner/pool/common.go b/runner/pool/common.go index 607e1cce..7479ef2e 100644 --- a/runner/pool/common.go +++ b/runner/pool/common.go @@ -4,10 +4,11 @@ import ( "net/url" "strings" - runnerErrors "github.com/cloudbase/garm-provider-common/errors" - "github.com/cloudbase/garm/params" "github.com/google/go-github/v57/github" "github.com/pkg/errors" + + runnerErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm/params" ) func validateHookRequest(controllerID, baseURL string, allHooks []*github.Hook, req *github.Hook) error { diff --git a/runner/pool/enterprise.go b/runner/pool/enterprise.go index e71f04d4..5e0b1e7e 100644 --- a/runner/pool/enterprise.go +++ b/runner/pool/enterprise.go @@ -10,6 +10,9 @@ import ( "strings" "sync" + "github.com/google/go-github/v57/github" + "github.com/pkg/errors" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" commonParams "github.com/cloudbase/garm-provider-common/params" dbCommon "github.com/cloudbase/garm/database/common" @@ -17,9 +20,6 @@ import ( "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" "github.com/cloudbase/garm/util" - - "github.com/google/go-github/v57/github" - "github.com/pkg/errors" ) // test that we implement PoolManager @@ -77,7 +77,8 @@ type enterprise struct { mux sync.Mutex } -func (r *enterprise) findRunnerGroupByName(ctx context.Context, name string) (*github.EnterpriseRunnerGroup, error) { +func (e *enterprise) findRunnerGroupByName(name string) (*github.EnterpriseRunnerGroup, error) { + // nolint:golangci-lint,godox // TODO(gabriel-samfira): implement caching opts := github.ListEnterpriseRunnerGroupOptions{ ListOptions: github.ListOptions{ @@ -90,7 +91,7 @@ func (r *enterprise) findRunnerGroupByName(ctx context.Context, name string) (*g "ListOrganizationRunnerGroups", // label: operation metricsLabelEnterpriseScope, // label: scope ).Inc() - runnerGroups, ghResp, err := r.ghcEnterpriseCli.ListRunnerGroups(r.ctx, r.cfg.Name, &opts) + runnerGroups, ghResp, err := e.ghcEnterpriseCli.ListRunnerGroups(e.ctx, e.cfg.Name, &opts) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "ListOrganizationRunnerGroups", // label: operation @@ -115,10 +116,10 @@ func (r *enterprise) findRunnerGroupByName(ctx context.Context, name string) (*g return nil, errors.Wrap(runnerErrors.ErrNotFound, "runner group not found") } -func (r *enterprise) GetJITConfig(ctx context.Context, instance string, pool params.Pool, labels []string) (jitConfigMap map[string]string, runner *github.Runner, err error) { +func (e *enterprise) GetJITConfig(ctx context.Context, instance string, pool params.Pool, labels []string) (jitConfigMap map[string]string, runner *github.Runner, err error) { var rg int64 = 1 if pool.GitHubRunnerGroup != "" { - runnerGroup, err := r.findRunnerGroupByName(ctx, pool.GitHubRunnerGroup) + runnerGroup, err := e.findRunnerGroupByName(pool.GitHubRunnerGroup) if err != nil { return nil, nil, fmt.Errorf("failed to find runner group: %w", err) } @@ -129,6 +130,7 @@ func (r *enterprise) GetJITConfig(ctx context.Context, instance string, pool par Name: instance, RunnerGroupID: rg, Labels: labels, + // nolint:golangci-lint,godox // TODO(gabriel-samfira): Should we make this configurable? WorkFolder: github.String("_work"), } @@ -136,7 +138,7 @@ func (r *enterprise) GetJITConfig(ctx context.Context, instance string, pool par "GenerateEnterpriseJITConfig", // label: operation metricsLabelEnterpriseScope, // label: scope ).Inc() - jitConfig, resp, err := r.ghcEnterpriseCli.GenerateEnterpriseJITConfig(ctx, r.cfg.Name, &req) + jitConfig, resp, err := e.ghcEnterpriseCli.GenerateEnterpriseJITConfig(ctx, e.cfg.Name, &req) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "GenerateEnterpriseJITConfig", // label: operation @@ -155,7 +157,7 @@ func (r *enterprise) GetJITConfig(ctx context.Context, instance string, pool par "RemoveRunner", // label: operation metricsLabelEnterpriseScope, // label: scope ).Inc() - _, innerErr := r.ghcEnterpriseCli.RemoveRunner(r.ctx, r.cfg.Name, runner.GetID()) + _, innerErr := e.ghcEnterpriseCli.RemoveRunner(e.ctx, e.cfg.Name, runner.GetID()) if innerErr != nil { metrics.GithubOperationFailedCount.WithLabelValues( "RemoveRunner", // label: operation @@ -164,7 +166,7 @@ func (r *enterprise) GetJITConfig(ctx context.Context, instance string, pool par } slog.With(slog.Any("error", innerErr)).ErrorContext( ctx, "failed to remove runner", - "runner_id", runner.GetID(), "organization", r.cfg.Name) + "runner_id", runner.GetID(), "organization", e.cfg.Name) } }() @@ -181,23 +183,23 @@ func (r *enterprise) GetJITConfig(ctx context.Context, instance string, pool par return ret, jitConfig.Runner, nil } -func (r *enterprise) GithubCLI() common.GithubClient { - return r.ghcli +func (e *enterprise) GithubCLI() common.GithubClient { + return e.ghcli } func (e *enterprise) PoolType() params.PoolType { return params.EnterprisePool } -func (r *enterprise) GetRunnerInfoFromWorkflow(job params.WorkflowJob) (params.RunnerInfo, error) { - if err := r.ValidateOwner(job); err != nil { +func (e *enterprise) GetRunnerInfoFromWorkflow(job params.WorkflowJob) (params.RunnerInfo, error) { + if err := e.ValidateOwner(job); err != nil { return params.RunnerInfo{}, errors.Wrap(err, "validating owner") } metrics.GithubOperationCount.WithLabelValues( "GetWorkflowJobByID", // label: operation metricsLabelEnterpriseScope, // label: scope ).Inc() - workflow, ghResp, err := r.ghcli.GetWorkflowJobByID(r.ctx, job.Repository.Owner.Login, job.Repository.Name, job.WorkflowJob.ID) + workflow, ghResp, err := e.ghcli.GetWorkflowJobByID(e.ctx, job.Repository.Owner.Login, job.Repository.Name, job.WorkflowJob.ID) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "GetWorkflowJobByID", // label: operation @@ -218,29 +220,29 @@ func (r *enterprise) GetRunnerInfoFromWorkflow(job params.WorkflowJob) (params.R return params.RunnerInfo{}, fmt.Errorf("failed to find runner name from workflow") } -func (r *enterprise) UpdateState(param params.UpdatePoolStateParams) error { - r.mux.Lock() - defer r.mux.Unlock() +func (e *enterprise) UpdateState(param params.UpdatePoolStateParams) error { + e.mux.Lock() + defer e.mux.Unlock() - r.cfg.WebhookSecret = param.WebhookSecret + e.cfg.WebhookSecret = param.WebhookSecret if param.InternalConfig != nil { - r.cfgInternal = *param.InternalConfig + e.cfgInternal = *param.InternalConfig } - ghc, ghcEnterprise, err := util.GithubClient(r.ctx, r.GetGithubToken(), r.cfgInternal.GithubCredentialsDetails) + ghc, ghcEnterprise, err := util.GithubClient(e.ctx, e.GetGithubToken(), e.cfgInternal.GithubCredentialsDetails) if err != nil { return errors.Wrap(err, "getting github client") } - r.ghcli = ghc - r.ghcEnterpriseCli = ghcEnterprise + e.ghcli = ghc + e.ghcEnterpriseCli = ghcEnterprise return nil } -func (r *enterprise) GetGithubToken() string { - return r.cfgInternal.OAuth2Token +func (e *enterprise) GetGithubToken() string { + return e.cfgInternal.OAuth2Token } -func (r *enterprise) GetGithubRunners() ([]*github.Runner, error) { +func (e *enterprise) GetGithubRunners() ([]*github.Runner, error) { opts := github.ListOptions{ PerPage: 100, } @@ -251,7 +253,7 @@ func (r *enterprise) GetGithubRunners() ([]*github.Runner, error) { "ListRunners", // label: operation metricsLabelEnterpriseScope, // label: scope ).Inc() - runners, ghResp, err := r.ghcEnterpriseCli.ListRunners(r.ctx, r.cfg.Name, &opts) + runners, ghResp, err := e.ghcEnterpriseCli.ListRunners(e.ctx, e.cfg.Name, &opts) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "ListRunners", // label: operation @@ -271,14 +273,14 @@ func (r *enterprise) GetGithubRunners() ([]*github.Runner, error) { return allRunners, nil } -func (r *enterprise) FetchTools() ([]commonParams.RunnerApplicationDownload, error) { - r.mux.Lock() - defer r.mux.Unlock() +func (e *enterprise) FetchTools() ([]commonParams.RunnerApplicationDownload, error) { + e.mux.Lock() + defer e.mux.Unlock() metrics.GithubOperationCount.WithLabelValues( "ListRunnerApplicationDownloads", // label: operation metricsLabelEnterpriseScope, // label: scope ).Inc() - tools, ghResp, err := r.ghcEnterpriseCli.ListRunnerApplicationDownloads(r.ctx, r.cfg.Name) + tools, ghResp, err := e.ghcEnterpriseCli.ListRunnerApplicationDownloads(e.ctx, e.cfg.Name) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "ListRunnerApplicationDownloads", // label: operation @@ -301,16 +303,16 @@ func (r *enterprise) FetchTools() ([]commonParams.RunnerApplicationDownload, err return ret, nil } -func (r *enterprise) FetchDbInstances() ([]params.Instance, error) { - return r.store.ListEnterpriseInstances(r.ctx, r.id) +func (e *enterprise) FetchDbInstances() ([]params.Instance, error) { + return e.store.ListEnterpriseInstances(e.ctx, e.id) } -func (r *enterprise) RemoveGithubRunner(runnerID int64) (*github.Response, error) { +func (e *enterprise) RemoveGithubRunner(runnerID int64) (*github.Response, error) { metrics.GithubOperationCount.WithLabelValues( "RemoveRunner", // label: operation metricsLabelEnterpriseScope, // label: scope ).Inc() - ghResp, err := r.ghcEnterpriseCli.RemoveRunner(r.ctx, r.cfg.Name, runnerID) + ghResp, err := e.ghcEnterpriseCli.RemoveRunner(e.ctx, e.cfg.Name, runnerID) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "RemoveRunner", // label: operation @@ -321,30 +323,29 @@ func (r *enterprise) RemoveGithubRunner(runnerID int64) (*github.Response, error return ghResp, nil } -func (r *enterprise) ListPools() ([]params.Pool, error) { - pools, err := r.store.ListEnterprisePools(r.ctx, r.id) +func (e *enterprise) ListPools() ([]params.Pool, error) { + pools, err := e.store.ListEnterprisePools(e.ctx, e.id) if err != nil { return nil, errors.Wrap(err, "fetching pools") } return pools, nil } -func (r *enterprise) GithubURL() string { - return fmt.Sprintf("%s/enterprises/%s", r.cfgInternal.GithubCredentialsDetails.BaseURL, r.cfg.Name) +func (e *enterprise) GithubURL() string { + return fmt.Sprintf("%s/enterprises/%s", e.cfgInternal.GithubCredentialsDetails.BaseURL, e.cfg.Name) } -func (r *enterprise) JwtToken() string { - return r.cfgInternal.JWTSecret +func (e *enterprise) JwtToken() string { + return e.cfgInternal.JWTSecret } -func (r *enterprise) GetGithubRegistrationToken() (string, error) { +func (e *enterprise) GetGithubRegistrationToken() (string, error) { metrics.GithubOperationCount.WithLabelValues( "CreateRegistrationToken", // label: operation metricsLabelEnterpriseScope, // label: scope ).Inc() - tk, ghResp, err := r.ghcEnterpriseCli.CreateRegistrationToken(r.ctx, r.cfg.Name) - + tk, ghResp, err := e.ghcEnterpriseCli.CreateRegistrationToken(e.ctx, e.cfg.Name) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "CreateRegistrationToken", // label: operation @@ -358,49 +359,49 @@ func (r *enterprise) GetGithubRegistrationToken() (string, error) { return *tk.Token, nil } -func (r *enterprise) String() string { - return r.cfg.Name +func (e *enterprise) String() string { + return e.cfg.Name } -func (r *enterprise) WebhookSecret() string { - return r.cfg.WebhookSecret +func (e *enterprise) WebhookSecret() string { + return e.cfg.WebhookSecret } -func (r *enterprise) FindPoolByTags(labels []string) (params.Pool, error) { - pool, err := r.store.FindEnterprisePoolByTags(r.ctx, r.id, labels) +func (e *enterprise) FindPoolByTags(labels []string) (params.Pool, error) { + pool, err := e.store.FindEnterprisePoolByTags(e.ctx, e.id, labels) if err != nil { return params.Pool{}, errors.Wrap(err, "fetching suitable pool") } return pool, nil } -func (r *enterprise) GetPoolByID(poolID string) (params.Pool, error) { - pool, err := r.store.GetEnterprisePool(r.ctx, r.id, poolID) +func (e *enterprise) GetPoolByID(poolID string) (params.Pool, error) { + pool, err := e.store.GetEnterprisePool(e.ctx, e.id, poolID) if err != nil { return params.Pool{}, errors.Wrap(err, "fetching pool") } return pool, nil } -func (r *enterprise) ValidateOwner(job params.WorkflowJob) error { - if !strings.EqualFold(job.Enterprise.Slug, r.cfg.Name) { +func (e *enterprise) ValidateOwner(job params.WorkflowJob) error { + if !strings.EqualFold(job.Enterprise.Slug, e.cfg.Name) { return runnerErrors.NewBadRequestError("job not meant for this pool manager") } return nil } -func (r *enterprise) ID() string { - return r.id +func (e *enterprise) ID() string { + return e.id } -func (r *enterprise) InstallHook(ctx context.Context, req *github.Hook) (params.HookInfo, error) { +func (e *enterprise) InstallHook(_ context.Context, _ *github.Hook) (params.HookInfo, error) { return params.HookInfo{}, fmt.Errorf("not implemented") } -func (r *enterprise) UninstallHook(ctx context.Context, url string) error { +func (e *enterprise) UninstallHook(_ context.Context, _ string) error { return fmt.Errorf("not implemented") } -func (r *enterprise) GetHookInfo(ctx context.Context) (params.HookInfo, error) { +func (e *enterprise) GetHookInfo(_ context.Context) (params.HookInfo, error) { return params.HookInfo{}, fmt.Errorf("not implemented") } diff --git a/runner/pool/interfaces.go b/runner/pool/interfaces.go index 71a24cbe..0ea446e9 100644 --- a/runner/pool/interfaces.go +++ b/runner/pool/interfaces.go @@ -17,11 +17,11 @@ package pool import ( "context" + "github.com/google/go-github/v57/github" + commonParams "github.com/cloudbase/garm-provider-common/params" "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" - - "github.com/google/go-github/v57/github" ) type poolHelper interface { diff --git a/runner/pool/organization.go b/runner/pool/organization.go index 0eee23f4..aa434141 100644 --- a/runner/pool/organization.go +++ b/runner/pool/organization.go @@ -24,6 +24,9 @@ import ( "strings" "sync" + "github.com/google/go-github/v57/github" + "github.com/pkg/errors" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" commonParams "github.com/cloudbase/garm-provider-common/params" dbCommon "github.com/cloudbase/garm/database/common" @@ -31,9 +34,6 @@ import ( "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" "github.com/cloudbase/garm/util" - - "github.com/google/go-github/v57/github" - "github.com/pkg/errors" ) // test that we implement PoolManager @@ -89,7 +89,8 @@ type organization struct { mux sync.Mutex } -func (r *organization) findRunnerGroupByName(ctx context.Context, name string) (*github.RunnerGroup, error) { +func (o *organization) findRunnerGroupByName(name string) (*github.RunnerGroup, error) { + // nolint:golangci-lint,godox // TODO(gabriel-samfira): implement caching opts := github.ListOrgRunnerGroupOptions{ ListOptions: github.ListOptions{ @@ -102,7 +103,7 @@ func (r *organization) findRunnerGroupByName(ctx context.Context, name string) ( "ListOrganizationRunnerGroups", // label: operation metricsLabelOrganizationScope, // label: scope ).Inc() - runnerGroups, ghResp, err := r.ghcli.ListOrganizationRunnerGroups(r.ctx, r.cfg.Name, &opts) + runnerGroups, ghResp, err := o.ghcli.ListOrganizationRunnerGroups(o.ctx, o.cfg.Name, &opts) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "ListOrganizationRunnerGroups", // label: operation @@ -127,10 +128,10 @@ func (r *organization) findRunnerGroupByName(ctx context.Context, name string) ( return nil, errors.Wrap(runnerErrors.ErrNotFound, "runner group not found") } -func (r *organization) GetJITConfig(ctx context.Context, instance string, pool params.Pool, labels []string) (jitConfigMap map[string]string, runner *github.Runner, err error) { +func (o *organization) GetJITConfig(ctx context.Context, instance string, pool params.Pool, labels []string) (jitConfigMap map[string]string, runner *github.Runner, err error) { var rg int64 = 1 if pool.GitHubRunnerGroup != "" { - runnerGroup, err := r.findRunnerGroupByName(ctx, pool.GitHubRunnerGroup) + runnerGroup, err := o.findRunnerGroupByName(pool.GitHubRunnerGroup) if err != nil { return nil, nil, fmt.Errorf("failed to find runner group: %w", err) } @@ -141,6 +142,7 @@ func (r *organization) GetJITConfig(ctx context.Context, instance string, pool p Name: instance, RunnerGroupID: rg, Labels: labels, + // nolint:golangci-lint,godox // TODO(gabriel-samfira): Should we make this configurable? WorkFolder: github.String("_work"), } @@ -148,7 +150,7 @@ func (r *organization) GetJITConfig(ctx context.Context, instance string, pool p "GenerateOrgJITConfig", // label: operation metricsLabelOrganizationScope, // label: scope ).Inc() - jitConfig, resp, err := r.ghcli.GenerateOrgJITConfig(ctx, r.cfg.Name, &req) + jitConfig, resp, err := o.ghcli.GenerateOrgJITConfig(ctx, o.cfg.Name, &req) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "GenerateOrgJITConfig", // label: operation @@ -167,7 +169,7 @@ func (r *organization) GetJITConfig(ctx context.Context, instance string, pool p "RemoveOrganizationRunner", // label: operation metricsLabelOrganizationScope, // label: scope ).Inc() - _, innerErr := r.ghcli.RemoveOrganizationRunner(r.ctx, r.cfg.Name, runner.GetID()) + _, innerErr := o.ghcli.RemoveOrganizationRunner(o.ctx, o.cfg.Name, runner.GetID()) if innerErr != nil { metrics.GithubOperationFailedCount.WithLabelValues( "RemoveOrganizationRunner", // label: operation @@ -176,7 +178,7 @@ func (r *organization) GetJITConfig(ctx context.Context, instance string, pool p } slog.With(slog.Any("error", innerErr)).ErrorContext( ctx, "failed to remove runner", - "runner_id", runner.GetID(), "organization", r.cfg.Name) + "runner_id", runner.GetID(), "organization", o.cfg.Name) } }() @@ -193,23 +195,23 @@ func (r *organization) GetJITConfig(ctx context.Context, instance string, pool p return ret, runner, nil } -func (r *organization) GithubCLI() common.GithubClient { - return r.ghcli +func (o *organization) GithubCLI() common.GithubClient { + return o.ghcli } func (o *organization) PoolType() params.PoolType { return params.OrganizationPool } -func (r *organization) GetRunnerInfoFromWorkflow(job params.WorkflowJob) (params.RunnerInfo, error) { - if err := r.ValidateOwner(job); err != nil { +func (o *organization) GetRunnerInfoFromWorkflow(job params.WorkflowJob) (params.RunnerInfo, error) { + if err := o.ValidateOwner(job); err != nil { return params.RunnerInfo{}, errors.Wrap(err, "validating owner") } metrics.GithubOperationCount.WithLabelValues( "GetWorkflowJobByID", // label: operation metricsLabelOrganizationScope, // label: scope ).Inc() - workflow, ghResp, err := r.ghcli.GetWorkflowJobByID(r.ctx, job.Organization.Login, job.Repository.Name, job.WorkflowJob.ID) + workflow, ghResp, err := o.ghcli.GetWorkflowJobByID(o.ctx, job.Organization.Login, job.Repository.Name, job.WorkflowJob.ID) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "GetWorkflowJobByID", // label: operation @@ -230,28 +232,28 @@ func (r *organization) GetRunnerInfoFromWorkflow(job params.WorkflowJob) (params return params.RunnerInfo{}, fmt.Errorf("failed to find runner name from workflow") } -func (r *organization) UpdateState(param params.UpdatePoolStateParams) error { - r.mux.Lock() - defer r.mux.Unlock() +func (o *organization) UpdateState(param params.UpdatePoolStateParams) error { + o.mux.Lock() + defer o.mux.Unlock() - r.cfg.WebhookSecret = param.WebhookSecret + o.cfg.WebhookSecret = param.WebhookSecret if param.InternalConfig != nil { - r.cfgInternal = *param.InternalConfig + o.cfgInternal = *param.InternalConfig } - ghc, _, err := util.GithubClient(r.ctx, r.GetGithubToken(), r.cfgInternal.GithubCredentialsDetails) + ghc, _, err := util.GithubClient(o.ctx, o.GetGithubToken(), o.cfgInternal.GithubCredentialsDetails) if err != nil { return errors.Wrap(err, "getting github client") } - r.ghcli = ghc + o.ghcli = ghc return nil } -func (r *organization) GetGithubToken() string { - return r.cfgInternal.OAuth2Token +func (o *organization) GetGithubToken() string { + return o.cfgInternal.OAuth2Token } -func (r *organization) GetGithubRunners() ([]*github.Runner, error) { +func (o *organization) GetGithubRunners() ([]*github.Runner, error) { opts := github.ListOptions{ PerPage: 100, } @@ -262,7 +264,7 @@ func (r *organization) GetGithubRunners() ([]*github.Runner, error) { "ListOrganizationRunners", // label: operation metricsLabelOrganizationScope, // label: scope ).Inc() - runners, ghResp, err := r.ghcli.ListOrganizationRunners(r.ctx, r.cfg.Name, &opts) + runners, ghResp, err := o.ghcli.ListOrganizationRunners(o.ctx, o.cfg.Name, &opts) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "ListOrganizationRunners", // label: operation @@ -283,14 +285,14 @@ func (r *organization) GetGithubRunners() ([]*github.Runner, error) { return allRunners, nil } -func (r *organization) FetchTools() ([]commonParams.RunnerApplicationDownload, error) { - r.mux.Lock() - defer r.mux.Unlock() +func (o *organization) FetchTools() ([]commonParams.RunnerApplicationDownload, error) { + o.mux.Lock() + defer o.mux.Unlock() metrics.GithubOperationCount.WithLabelValues( "ListOrganizationRunnerApplicationDownloads", // label: operation metricsLabelOrganizationScope, // label: scope ).Inc() - tools, ghResp, err := r.ghcli.ListOrganizationRunnerApplicationDownloads(r.ctx, r.cfg.Name) + tools, ghResp, err := o.ghcli.ListOrganizationRunnerApplicationDownloads(o.ctx, o.cfg.Name) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "ListOrganizationRunnerApplicationDownloads", // label: operation @@ -313,17 +315,17 @@ func (r *organization) FetchTools() ([]commonParams.RunnerApplicationDownload, e return ret, nil } -func (r *organization) FetchDbInstances() ([]params.Instance, error) { - return r.store.ListOrgInstances(r.ctx, r.id) +func (o *organization) FetchDbInstances() ([]params.Instance, error) { + return o.store.ListOrgInstances(o.ctx, o.id) } -func (r *organization) RemoveGithubRunner(runnerID int64) (*github.Response, error) { +func (o *organization) RemoveGithubRunner(runnerID int64) (*github.Response, error) { metrics.GithubOperationCount.WithLabelValues( "RemoveRunner", // label: operation metricsLabelOrganizationScope, // label: scope ).Inc() - ghResp, err := r.ghcli.RemoveOrganizationRunner(r.ctx, r.cfg.Name, runnerID) + ghResp, err := o.ghcli.RemoveOrganizationRunner(o.ctx, o.cfg.Name, runnerID) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "RemoveRunner", // label: operation @@ -335,29 +337,28 @@ func (r *organization) RemoveGithubRunner(runnerID int64) (*github.Response, err return ghResp, nil } -func (r *organization) ListPools() ([]params.Pool, error) { - pools, err := r.store.ListOrgPools(r.ctx, r.id) +func (o *organization) ListPools() ([]params.Pool, error) { + pools, err := o.store.ListOrgPools(o.ctx, o.id) if err != nil { return nil, errors.Wrap(err, "fetching pools") } return pools, nil } -func (r *organization) GithubURL() string { - return fmt.Sprintf("%s/%s", r.cfgInternal.GithubCredentialsDetails.BaseURL, r.cfg.Name) +func (o *organization) GithubURL() string { + return fmt.Sprintf("%s/%s", o.cfgInternal.GithubCredentialsDetails.BaseURL, o.cfg.Name) } -func (r *organization) JwtToken() string { - return r.cfgInternal.JWTSecret +func (o *organization) JwtToken() string { + return o.cfgInternal.JWTSecret } -func (r *organization) GetGithubRegistrationToken() (string, error) { +func (o *organization) GetGithubRegistrationToken() (string, error) { metrics.GithubOperationCount.WithLabelValues( "CreateOrganizationRegistrationToken", // label: operation metricsLabelOrganizationScope, // label: scope ).Inc() - tk, ghResp, err := r.ghcli.CreateOrganizationRegistrationToken(r.ctx, r.cfg.Name) - + tk, ghResp, err := o.ghcli.CreateOrganizationRegistrationToken(o.ctx, o.cfg.Name) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "CreateOrganizationRegistrationToken", // label: operation @@ -372,42 +373,42 @@ func (r *organization) GetGithubRegistrationToken() (string, error) { return *tk.Token, nil } -func (r *organization) String() string { - return r.cfg.Name +func (o *organization) String() string { + return o.cfg.Name } -func (r *organization) WebhookSecret() string { - return r.cfg.WebhookSecret +func (o *organization) WebhookSecret() string { + return o.cfg.WebhookSecret } -func (r *organization) FindPoolByTags(labels []string) (params.Pool, error) { - pool, err := r.store.FindOrganizationPoolByTags(r.ctx, r.id, labels) +func (o *organization) FindPoolByTags(labels []string) (params.Pool, error) { + pool, err := o.store.FindOrganizationPoolByTags(o.ctx, o.id, labels) if err != nil { return params.Pool{}, errors.Wrap(err, "fetching suitable pool") } return pool, nil } -func (r *organization) GetPoolByID(poolID string) (params.Pool, error) { - pool, err := r.store.GetOrganizationPool(r.ctx, r.id, poolID) +func (o *organization) GetPoolByID(poolID string) (params.Pool, error) { + pool, err := o.store.GetOrganizationPool(o.ctx, o.id, poolID) if err != nil { return params.Pool{}, errors.Wrap(err, "fetching pool") } return pool, nil } -func (r *organization) ValidateOwner(job params.WorkflowJob) error { - if !strings.EqualFold(job.Organization.Login, r.cfg.Name) { +func (o *organization) ValidateOwner(job params.WorkflowJob) error { + if !strings.EqualFold(job.Organization.Login, o.cfg.Name) { return runnerErrors.NewBadRequestError("job not meant for this pool manager") } return nil } -func (r *organization) ID() string { - return r.id +func (o *organization) ID() string { + return o.id } -func (r *organization) listHooks(ctx context.Context) ([]*github.Hook, error) { +func (o *organization) listHooks(ctx context.Context) ([]*github.Hook, error) { opts := github.ListOptions{ PerPage: 100, } @@ -417,7 +418,7 @@ func (r *organization) listHooks(ctx context.Context) ([]*github.Hook, error) { "ListOrgHooks", // label: operation metricsLabelOrganizationScope, // label: scope ).Inc() - hooks, ghResp, err := r.ghcli.ListOrgHooks(ctx, r.cfg.Name, &opts) + hooks, ghResp, err := o.ghcli.ListOrgHooks(ctx, o.cfg.Name, &opts) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "ListOrgHooks", // label: operation @@ -437,13 +438,13 @@ func (r *organization) listHooks(ctx context.Context) ([]*github.Hook, error) { return allHooks, nil } -func (r *organization) InstallHook(ctx context.Context, req *github.Hook) (params.HookInfo, error) { - allHooks, err := r.listHooks(ctx) +func (o *organization) InstallHook(ctx context.Context, req *github.Hook) (params.HookInfo, error) { + allHooks, err := o.listHooks(ctx) if err != nil { return params.HookInfo{}, errors.Wrap(err, "listing hooks") } - if err := validateHookRequest(r.cfgInternal.ControllerID, r.cfgInternal.BaseWebhookURL, allHooks, req); err != nil { + if err := validateHookRequest(o.cfgInternal.ControllerID, o.cfgInternal.BaseWebhookURL, allHooks, req); err != nil { return params.HookInfo{}, errors.Wrap(err, "validating hook request") } @@ -452,7 +453,7 @@ func (r *organization) InstallHook(ctx context.Context, req *github.Hook) (param metricsLabelOrganizationScope, // label: scope ).Inc() - hook, _, err := r.ghcli.CreateOrgHook(ctx, r.cfg.Name, req) + hook, _, err := o.ghcli.CreateOrgHook(ctx, o.cfg.Name, req) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "CreateOrgHook", // label: operation @@ -466,7 +467,7 @@ func (r *organization) InstallHook(ctx context.Context, req *github.Hook) (param metricsLabelOrganizationScope, // label: scope ).Inc() - if _, err := r.ghcli.PingOrgHook(ctx, r.cfg.Name, hook.GetID()); err != nil { + if _, err := o.ghcli.PingOrgHook(ctx, o.cfg.Name, hook.GetID()); err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "PingOrgHook", // label: operation metricsLabelOrganizationScope, // label: scope @@ -477,8 +478,8 @@ func (r *organization) InstallHook(ctx context.Context, req *github.Hook) (param return hookToParamsHookInfo(hook), nil } -func (r *organization) UninstallHook(ctx context.Context, url string) error { - allHooks, err := r.listHooks(ctx) +func (o *organization) UninstallHook(ctx context.Context, url string) error { + allHooks, err := o.listHooks(ctx) if err != nil { return errors.Wrap(err, "listing hooks") } @@ -489,7 +490,7 @@ func (r *organization) UninstallHook(ctx context.Context, url string) error { "DeleteOrgHook", // label: operation metricsLabelOrganizationScope, // label: scope ).Inc() - _, err = r.ghcli.DeleteOrgHook(ctx, r.cfg.Name, hook.GetID()) + _, err = o.ghcli.DeleteOrgHook(ctx, o.cfg.Name, hook.GetID()) if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "DeleteOrgHook", // label: operation @@ -503,15 +504,15 @@ func (r *organization) UninstallHook(ctx context.Context, url string) error { return nil } -func (r *organization) GetHookInfo(ctx context.Context) (params.HookInfo, error) { - allHooks, err := r.listHooks(ctx) +func (o *organization) GetHookInfo(ctx context.Context) (params.HookInfo, error) { + allHooks, err := o.listHooks(ctx) if err != nil { return params.HookInfo{}, errors.Wrap(err, "listing hooks") } for _, hook := range allHooks { hookInfo := hookToParamsHookInfo(hook) - if strings.EqualFold(hookInfo.URL, r.cfgInternal.ControllerWebhookURL) { + if strings.EqualFold(hookInfo.URL, o.cfgInternal.ControllerWebhookURL) { return hookInfo, nil } } diff --git a/runner/pool/pool.go b/runner/pool/pool.go index 8e69ff03..edc95a7d 100644 --- a/runner/pool/pool.go +++ b/runner/pool/pool.go @@ -25,19 +25,18 @@ import ( "sync" "time" - commonParams "github.com/cloudbase/garm-provider-common/params" + "github.com/google/go-github/v57/github" + "github.com/google/uuid" + "github.com/pkg/errors" + "golang.org/x/sync/errgroup" runnerErrors "github.com/cloudbase/garm-provider-common/errors" + commonParams "github.com/cloudbase/garm-provider-common/params" "github.com/cloudbase/garm-provider-common/util" "github.com/cloudbase/garm/auth" dbCommon "github.com/cloudbase/garm/database/common" "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" - - "github.com/google/go-github/v57/github" - "github.com/google/uuid" - "github.com/pkg/errors" - "golang.org/x/sync/errgroup" ) var ( @@ -55,6 +54,8 @@ var ( const ( // maxCreateAttempts is the number of times we will attempt to create an instance // before we give up. + // + // nolint:golangci-lint,godox // TODO: make this configurable(?) maxCreateAttempts = 5 @@ -245,7 +246,7 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error { return errors.Wrap(err, "updating runner") } // Set triggeredBy here so we break the lock on any potential queued job. - triggeredBy = jobIdFromLabels(instance.AditionalLabels) + triggeredBy = jobIDFromLabels(instance.AditionalLabels) // A runner has picked up the job, and is now running it. It may need to be replaced if the pool has // a minimum number of idle runners configured. @@ -262,14 +263,14 @@ func (r *basePoolManager) HandleWorkflowJob(job params.WorkflowJob) error { return nil } -func jobIdFromLabels(labels []string) int64 { +func jobIDFromLabels(labels []string) int64 { for _, lbl := range labels { if strings.HasPrefix(lbl, jobLabelPrefix) { - jobId, err := strconv.ParseInt(lbl[len(jobLabelPrefix):], 10, 64) + jobID, err := strconv.ParseInt(lbl[len(jobLabelPrefix):], 10, 64) if err != nil { return 0 } - return jobId + return jobID } } return 0 @@ -413,7 +414,7 @@ func (r *basePoolManager) cleanupOrphanedProviderRunners(runners []*github.Runne } defer r.keyMux.Unlock(instance.Name, false) - switch commonParams.InstanceStatus(instance.Status) { + switch instance.Status { case commonParams.InstancePendingCreate, commonParams.InstancePendingDelete, commonParams.InstancePendingForceDelete: // this instance is in the process of being created or is awaiting deletion. @@ -571,7 +572,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner) continue } - switch commonParams.InstanceStatus(dbInstance.Status) { + switch dbInstance.Status { case commonParams.InstancePendingDelete, commonParams.InstanceDeleting: // already marked for deletion or is in the process of being deleted. // Let consolidate take care of it. @@ -645,7 +646,7 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner) // Removed in the meantime? if resp != nil && resp.StatusCode == http.StatusNotFound { slog.DebugContext( - r.ctx, "runner dissapeared from github", + r.ctx, "runner disappeared from github", "runner_name", dbInstance.Name) } else { return errors.Wrap(err, "removing runner from github") @@ -670,14 +671,14 @@ func (r *basePoolManager) cleanupOrphanedGithubRunners(runners []*github.Runner) r.ctx, "instance is online but github reports runner as offline", "runner_name", dbInstance.Name) return nil - } else { - slog.InfoContext( - r.ctx, "instance was found in stopped state; starting", - "runner_name", dbInstance.Name) - //start the instance - if err := provider.Start(r.ctx, dbInstance.ProviderID); err != nil { - return errors.Wrapf(err, "starting instance %s", dbInstance.ProviderID) - } + } + + slog.InfoContext( + r.ctx, "instance was found in stopped state; starting", + "runner_name", dbInstance.Name) + + if err := provider.Start(r.ctx, dbInstance.ProviderID); err != nil { + return errors.Wrapf(err, "starting instance %s", dbInstance.ProviderID) } return nil }) @@ -1144,6 +1145,7 @@ func (r *basePoolManager) scaleDownOnePool(ctx context.Context, pool params.Pool // up by a runner, they are most likely stale and can be removed. For now, we can simply // remove jobs older than 10 minutes. // + // nolint:golangci-lint,godox // TODO: should probably allow aditional filters to list functions. Would help to filter by date // instead of returning a bunch of results and filtering manually. queued, err := r.store.ListEntityJobsByStatus(r.ctx, r.helper.PoolType(), r.helper.ID(), params.JobStatusQueued) @@ -1196,7 +1198,6 @@ func (r *basePoolManager) ensureIdleRunnersForOnePool(pool params.Pool) error { existingInstances, err := r.store.ListPoolInstances(r.ctx, pool.ID) if err != nil { return fmt.Errorf("failed to ensure minimum idle workers for pool %s: %w", pool.ID, err) - } if uint(len(existingInstances)) >= pool.MaxRunners { @@ -1223,7 +1224,7 @@ func (r *basePoolManager) ensureIdleRunnersForOnePool(pool params.Pool) error { if uint(projectedInstanceCount) > pool.MaxRunners { // ensure we don't go above max workers delta := projectedInstanceCount - int(pool.MaxRunners) - required = required - delta + required -= delta } } @@ -1278,6 +1279,7 @@ func (r *basePoolManager) retryFailedInstancesForOnePool(ctx context.Context, po slog.DebugContext( ctx, "attempting to clean up any previous instance", "runner_name", instance.Name) + // nolint:golangci-lint,godox // NOTE(gabriel-samfira): this is done in parallel. If there are many failed instances // this has the potential to create many API requests to the target provider. // TODO(gabriel-samfira): implement request throttling. @@ -1297,6 +1299,7 @@ func (r *basePoolManager) retryFailedInstancesForOnePool(ctx context.Context, po slog.DebugContext( ctx, "cleanup of previously failed instance complete", "runner_name", instance.Name) + // nolint:golangci-lint,godox // TODO(gabriel-samfira): Incrementing CreateAttempt should be done within a transaction. // It's fairly safe to do here (for now), as there should be no other code path that updates // an instance in this state. @@ -1506,6 +1509,7 @@ func (r *basePoolManager) deletePendingInstances() error { } func (r *basePoolManager) addPendingInstances() error { + // nolint:golangci-lint,godox // TODO: filter instances by status. instances, err := r.helper.FetchDbInstances() if err != nil { @@ -1772,6 +1776,7 @@ func (r *basePoolManager) consumeQueuedJobs() error { // was spawned. Unlock it and try again. A different job may have picked up // the runner. if err := r.store.UnlockJob(r.ctx, job.ID, r.ID()); err != nil { + // nolint:golangci-lint,godox // TODO: Implament a cache? Should we return here? slog.With(slog.Any("error", err)).ErrorContext( r.ctx, "failed to unlock job", @@ -1781,6 +1786,7 @@ func (r *basePoolManager) consumeQueuedJobs() error { } if job.LockedBy.String() == r.ID() { + // nolint:golangci-lint,godox // Job is locked by us. We must have already attepted to create a runner for it. Skip. // TODO(gabriel-samfira): create an in-memory state of existing runners that we can easily // check for existing pending or idle runners. If we can't find any, attempt to allocate another diff --git a/runner/pool/repository.go b/runner/pool/repository.go index 9ba77c13..14e80319 100644 --- a/runner/pool/repository.go +++ b/runner/pool/repository.go @@ -24,6 +24,9 @@ import ( "strings" "sync" + "github.com/google/go-github/v57/github" + "github.com/pkg/errors" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" commonParams "github.com/cloudbase/garm-provider-common/params" dbCommon "github.com/cloudbase/garm/database/common" @@ -31,9 +34,6 @@ import ( "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" "github.com/cloudbase/garm/util" - - "github.com/google/go-github/v57/github" - "github.com/pkg/errors" ) // test that we implement PoolManager @@ -91,12 +91,15 @@ type repository struct { mux sync.Mutex } +// nolint:golint,revive +// pool is used in enterprise and organzation func (r *repository) GetJITConfig(ctx context.Context, instance string, pool params.Pool, labels []string) (jitConfigMap map[string]string, runner *github.Runner, err error) { req := github.GenerateJITConfigRequest{ Name: instance, // At the repository level we only have the default runner group. RunnerGroupID: 1, Labels: labels, + // nolint:golangci-lint,godox // TODO(gabriel-samfira): Should we make this configurable? WorkFolder: github.String("_work"), } @@ -314,7 +317,6 @@ func (r *repository) GetGithubRegistrationToken() (string, error) { metricsLabelRepositoryScope, // label: scope ).Inc() tk, ghResp, err := r.ghcli.CreateRegistrationToken(r.ctx, r.cfg.Owner, r.cfg.Name) - if err != nil { metrics.GithubOperationFailedCount.WithLabelValues( "CreateRegistrationToken", // label: operation diff --git a/runner/pools.go b/runner/pools.go index 8fbe2b0e..16194f65 100644 --- a/runner/pools.go +++ b/runner/pools.go @@ -18,11 +18,11 @@ import ( "context" "fmt" + "github.com/pkg/errors" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/params" - - "github.com/pkg/errors" ) func (r *Runner) ListAllPools(ctx context.Context) ([]params.Pool, error) { @@ -110,13 +110,14 @@ func (r *Runner) UpdatePoolByID(ctx context.Context, poolID string, param params var newPool params.Pool - if pool.RepoID != "" { + switch { + case pool.RepoID != "": newPool, err = r.store.UpdateRepositoryPool(ctx, pool.RepoID, poolID, param) - } else if pool.OrgID != "" { + case pool.OrgID != "": newPool, err = r.store.UpdateOrganizationPool(ctx, pool.OrgID, poolID, param) - } else if pool.EnterpriseID != "" { + case pool.EnterpriseID != "": newPool, err = r.store.UpdateEnterprisePool(ctx, pool.EnterpriseID, poolID, param) - } else { + default: return params.Pool{}, fmt.Errorf("pool not found to a repo, org or enterprise") } diff --git a/runner/pools_test.go b/runner/pools_test.go index 94fee6b6..8bd33a5e 100644 --- a/runner/pools_test.go +++ b/runner/pools_test.go @@ -19,6 +19,8 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/suite" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/config" @@ -27,7 +29,6 @@ import ( garmTesting "github.com/cloudbase/garm/internal/testing" "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" - "github.com/stretchr/testify/suite" ) type PoolTestFixtures struct { @@ -207,7 +208,7 @@ func (s *PoolTestSuite) TestTestUpdatePoolByIDInvalidPoolID() { func (s *PoolTestSuite) TestTestUpdatePoolByIDRunnerBootstrapTimeoutFailed() { // this is already created in `SetupTest()` - var RunnerBootstrapTimeout uint = 0 + var RunnerBootstrapTimeout uint // default is 0 s.Fixtures.UpdatePoolParams.RunnerBootstrapTimeout = &RunnerBootstrapTimeout _, err := s.Runner.UpdatePoolByID(s.Fixtures.AdminContext, s.Fixtures.Pools[0].ID, s.Fixtures.UpdatePoolParams) diff --git a/runner/providers/external/external.go b/runner/providers/external/external.go index 11b614de..446f69a5 100644 --- a/runner/providers/external/external.go +++ b/runner/providers/external/external.go @@ -7,18 +7,16 @@ import ( "log/slog" "os/exec" - "github.com/cloudbase/garm-provider-common/execution" - - commonParams "github.com/cloudbase/garm-provider-common/params" + "github.com/pkg/errors" garmErrors "github.com/cloudbase/garm-provider-common/errors" + "github.com/cloudbase/garm-provider-common/execution" + commonParams "github.com/cloudbase/garm-provider-common/params" garmExec "github.com/cloudbase/garm-provider-common/util/exec" "github.com/cloudbase/garm/config" "github.com/cloudbase/garm/metrics" "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" - - "github.com/pkg/errors" ) var _ common.Provider = (*external)(nil) @@ -52,7 +50,7 @@ type external struct { environmentVariables []string } -func (e *external) validateResult(ctx context.Context, inst commonParams.ProviderInstance) error { +func (e *external) validateResult(inst commonParams.ProviderInstance) error { if inst.ProviderID == "" { return garmErrors.NewProviderError("missing provider ID") } @@ -106,7 +104,7 @@ func (e *external) CreateInstance(ctx context.Context, bootstrapParams commonPar return commonParams.ProviderInstance{}, garmErrors.NewProviderError("failed to decode response from binary: %s", err) } - if err := e.validateResult(ctx, param); err != nil { + if err := e.validateResult(param); err != nil { metrics.InstanceOperationFailedCount.WithLabelValues( "CreateInstance", // label: operation e.cfg.Name, // label: provider @@ -145,7 +143,6 @@ func (e *external) DeleteInstance(ctx context.Context, instance string) error { ).Inc() return garmErrors.NewProviderError("provider binary %s returned error: %s", e.execPath, err) } - } return nil } @@ -160,6 +157,7 @@ func (e *external) GetInstance(ctx context.Context, instance string) (commonPara } asEnv = append(asEnv, e.environmentVariables...) + // nolint:golangci-lint,godox // TODO(gabriel-samfira): handle error types. Of particular interest is to // know when the error is ErrNotFound. metrics.InstanceOperationCount.WithLabelValues( @@ -184,7 +182,7 @@ func (e *external) GetInstance(ctx context.Context, instance string) (commonPara return commonParams.ProviderInstance{}, garmErrors.NewProviderError("failed to decode response from binary: %s", err) } - if err := e.validateResult(ctx, param); err != nil { + if err := e.validateResult(param); err != nil { metrics.InstanceOperationFailedCount.WithLabelValues( "GetInstance", // label: operation e.cfg.Name, // label: provider @@ -230,7 +228,7 @@ func (e *external) ListInstances(ctx context.Context, poolID string) ([]commonPa ret := make([]commonParams.ProviderInstance, len(param)) for idx, inst := range param { - if err := e.validateResult(ctx, inst); err != nil { + if err := e.validateResult(inst); err != nil { metrics.InstanceOperationFailedCount.WithLabelValues( "ListInstances", // label: operation e.cfg.Name, // label: provider @@ -268,7 +266,7 @@ func (e *external) RemoveAllInstances(ctx context.Context) error { } // Stop shuts down the instance. -func (e *external) Stop(ctx context.Context, instance string, force bool) error { +func (e *external) Stop(ctx context.Context, instance string) error { asEnv := []string{ fmt.Sprintf("GARM_COMMAND=%s", execution.StopInstanceCommand), fmt.Sprintf("GARM_CONTROLLER_ID=%s", e.controllerID), diff --git a/runner/providers/providers.go b/runner/providers/providers.go index e9bb48ed..165fb585 100644 --- a/runner/providers/providers.go +++ b/runner/providers/providers.go @@ -18,12 +18,12 @@ import ( "context" "log/slog" + "github.com/pkg/errors" + "github.com/cloudbase/garm/config" "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" "github.com/cloudbase/garm/runner/providers/external" - - "github.com/pkg/errors" ) // LoadProvidersFromConfig loads all providers from the config and populates diff --git a/runner/repositories.go b/runner/repositories.go index 143bbd06..297b0f01 100644 --- a/runner/repositories.go +++ b/runner/repositories.go @@ -20,13 +20,13 @@ import ( "log/slog" "strings" + "github.com/pkg/errors" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/params" "github.com/cloudbase/garm/runner/common" "github.com/cloudbase/garm/util/appdefaults" - - "github.com/pkg/errors" ) func (r *Runner) CreateRepository(ctx context.Context, param params.CreateRepoParams) (repo params.Repository, err error) { @@ -143,12 +143,12 @@ func (r *Runner) DeleteRepository(ctx context.Context, repoID string, keepWebhoo } if len(pools) > 0 { - poolIds := []string{} + poolIDs := []string{} for _, pool := range pools { - poolIds = append(poolIds, pool.ID) + poolIDs = append(poolIDs, pool.ID) } - return runnerErrors.NewBadRequestError("repo has pools defined (%s)", strings.Join(poolIds, ", ")) + return runnerErrors.NewBadRequestError("repo has pools defined (%s)", strings.Join(poolIDs, ", ")) } if !keepWebhook && r.config.Default.EnableWebhookManagement { @@ -158,6 +158,7 @@ func (r *Runner) DeleteRepository(ctx context.Context, repoID string, keepWebhoo } if err := poolMgr.UninstallWebhook(ctx); err != nil { + // nolint:golangci-lint,godox // TODO(gabriel-samfira): Should we error out here? slog.With(slog.Any("error", err)).ErrorContext( ctx, "failed to uninstall webhook", @@ -270,6 +271,7 @@ func (r *Runner) DeleteRepoPool(ctx context.Context, repoID, poolID string) erro return errors.Wrap(err, "fetching instances") } + // nolint:golangci-lint,godox // TODO: implement a count function if len(instances) > 0 { runnerIDs := []string{} diff --git a/runner/repositories_test.go b/runner/repositories_test.go index e5b59ade..088301d3 100644 --- a/runner/repositories_test.go +++ b/runner/repositories_test.go @@ -19,6 +19,9 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" + runnerErrors "github.com/cloudbase/garm-provider-common/errors" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/config" @@ -29,9 +32,6 @@ import ( "github.com/cloudbase/garm/runner/common" runnerCommonMocks "github.com/cloudbase/garm/runner/common/mocks" runnerMocks "github.com/cloudbase/garm/runner/mocks" - - "github.com/stretchr/testify/mock" - "github.com/stretchr/testify/suite" ) type RepoTestFixtures struct { @@ -185,7 +185,7 @@ func (s *RepoTestSuite) TestCreateRepositoryEmptyParams() { } func (s *RepoTestSuite) TestCreateRepositoryMissingCredentials() { - s.Fixtures.CreateRepoParams.CredentialsName = "not-existent-creds-name" + s.Fixtures.CreateRepoParams.CredentialsName = notExistingCredentialsName _, err := s.Runner.CreateRepository(s.Fixtures.AdminContext, s.Fixtures.CreateRepoParams) @@ -312,7 +312,7 @@ func (s *RepoTestSuite) TestUpdateRepositoryErrUnauthorized() { } func (s *RepoTestSuite) TestUpdateRepositoryInvalidCreds() { - s.Fixtures.UpdateRepoParams.CredentialsName = "invalid-creds-name" + s.Fixtures.UpdateRepoParams.CredentialsName = invalidCredentialsName _, err := s.Runner.UpdateRepository(s.Fixtures.AdminContext, s.Fixtures.StoreRepos["test-repo-1"].ID, s.Fixtures.UpdateRepoParams) @@ -374,7 +374,7 @@ func (s *RepoTestSuite) TestCreateRepoPoolErrNotFound() { } func (s *RepoTestSuite) TestCreateRepoPoolFetchPoolParamsFailed() { - s.Fixtures.CreatePoolParams.ProviderName = "not-existent-provider-name" + s.Fixtures.CreatePoolParams.ProviderName = notExistingProviderName s.Fixtures.PoolMgrCtrlMock.On("GetRepoPoolManager", mock.AnythingOfType("params.Repository")).Return(s.Fixtures.PoolMgrMock, nil) diff --git a/runner/runner.go b/runner/runner.go index 55c23ae8..4cf45ba3 100644 --- a/runner/runner.go +++ b/runner/runner.go @@ -17,7 +17,7 @@ package runner import ( "context" "crypto/hmac" - "crypto/sha1" + "crypto/sha1" //nolint:golangci-lint,gosec // sha1 is used for github webhooks "crypto/sha256" "encoding/hex" "encoding/json" @@ -29,9 +29,14 @@ import ( "sync" "time" - commonParams "github.com/cloudbase/garm-provider-common/params" + "github.com/google/uuid" + "github.com/juju/clock" + "github.com/juju/retry" + "github.com/pkg/errors" + "golang.org/x/sync/errgroup" runnerErrors "github.com/cloudbase/garm-provider-common/errors" + commonParams "github.com/cloudbase/garm-provider-common/params" "github.com/cloudbase/garm-provider-common/util" "github.com/cloudbase/garm/auth" "github.com/cloudbase/garm/config" @@ -40,21 +45,15 @@ import ( "github.com/cloudbase/garm/runner/common" "github.com/cloudbase/garm/runner/pool" "github.com/cloudbase/garm/runner/providers" - "golang.org/x/sync/errgroup" - - "github.com/google/uuid" - "github.com/juju/clock" - "github.com/juju/retry" - "github.com/pkg/errors" ) func NewRunner(ctx context.Context, cfg config.Config, db dbCommon.Store) (*Runner, error) { - ctrlId, err := db.ControllerInfo() + ctrlID, err := db.ControllerInfo() if err != nil { return nil, errors.Wrap(err, "fetching controller info") } - providers, err := providers.LoadProvidersFromConfig(ctx, cfg, ctrlId.ControllerID.String()) + providers, err := providers.LoadProvidersFromConfig(ctx, cfg, ctrlID.ControllerID.String()) if err != nil { return nil, errors.Wrap(err, "loading providers") } @@ -66,7 +65,7 @@ func NewRunner(ctx context.Context, cfg config.Config, db dbCommon.Store) (*Runn } poolManagerCtrl := &poolManagerCtrl{ - controllerID: ctrlId.ControllerID.String(), + controllerID: ctrlID.ControllerID.String(), config: cfg, credentials: creds, repositories: map[string]common.PoolManager{}, @@ -80,7 +79,7 @@ func NewRunner(ctx context.Context, cfg config.Config, db dbCommon.Store) (*Runn poolManagerCtrl: poolManagerCtrl, providers: providers, credentials: creds, - controllerID: ctrlId.ControllerID, + controllerID: ctrlID.ControllerID, } if err := runner.loadReposOrgsAndEnterprises(); err != nil { @@ -118,7 +117,7 @@ func (p *poolManagerCtrl) CreateRepoPoolManager(ctx context.Context, repo params return poolManager, nil } -func (p *poolManagerCtrl) UpdateRepoPoolManager(ctx context.Context, repo params.Repository) (common.PoolManager, error) { +func (p *poolManagerCtrl) UpdateRepoPoolManager(_ context.Context, repo params.Repository) (common.PoolManager, error) { p.mux.Lock() defer p.mux.Unlock() @@ -184,7 +183,7 @@ func (p *poolManagerCtrl) CreateOrgPoolManager(ctx context.Context, org params.O return poolManager, nil } -func (p *poolManagerCtrl) UpdateOrgPoolManager(ctx context.Context, org params.Organization) (common.PoolManager, error) { +func (p *poolManagerCtrl) UpdateOrgPoolManager(_ context.Context, org params.Organization) (common.PoolManager, error) { p.mux.Lock() defer p.mux.Unlock() @@ -250,7 +249,7 @@ func (p *poolManagerCtrl) CreateEnterprisePoolManager(ctx context.Context, enter return poolManager, nil } -func (p *poolManagerCtrl) UpdateEnterprisePoolManager(ctx context.Context, enterprise params.Enterprise) (common.PoolManager, error) { +func (p *poolManagerCtrl) UpdateEnterprisePoolManager(_ context.Context, enterprise params.Enterprise) (common.PoolManager, error) { p.mux.Lock() defer p.mux.Unlock() @@ -627,34 +626,34 @@ func (r *Runner) Wait() error { return errors.Wrap(err, "fetch enterprise pool managers") } - for poolId, repo := range repos { + for poolID, repo := range repos { wg.Add(1) go func(id string, poolMgr common.PoolManager) { defer wg.Done() if err := poolMgr.Wait(); err != nil { slog.With(slog.Any("error", err)).ErrorContext(r.ctx, "timed out waiting for pool manager to exit", "pool_id", id, "pool_mgr_id", poolMgr.ID()) } - }(poolId, repo) + }(poolID, repo) } - for poolId, org := range orgs { + for poolID, org := range orgs { wg.Add(1) go func(id string, poolMgr common.PoolManager) { defer wg.Done() if err := poolMgr.Wait(); err != nil { slog.With(slog.Any("error", err)).ErrorContext(r.ctx, "timed out waiting for pool manager to exit", "pool_id", id) } - }(poolId, org) + }(poolID, org) } - for poolId, enterprise := range enterprises { + for poolID, enterprise := range enterprises { wg.Add(1) go func(id string, poolMgr common.PoolManager) { defer wg.Done() if err := poolMgr.Wait(); err != nil { slog.With(slog.Any("error", err)).ErrorContext(r.ctx, "timed out waiting for pool manager to exit", "pool_id", id) } - }(poolId, enterprise) + }(poolID, enterprise) } wg.Wait() @@ -904,7 +903,8 @@ func (r *Runner) getPoolManagerFromInstance(ctx context.Context, instance params var poolMgr common.PoolManager - if pool.RepoID != "" { + switch { + case pool.RepoID != "": repo, err := r.store.GetRepositoryByID(ctx, pool.RepoID) if err != nil { return nil, errors.Wrap(err, "fetching repo") @@ -913,7 +913,7 @@ func (r *Runner) getPoolManagerFromInstance(ctx context.Context, instance params if err != nil { return nil, errors.Wrapf(err, "fetching pool manager for repo %s", pool.RepoName) } - } else if pool.OrgID != "" { + case pool.OrgID != "": org, err := r.store.GetOrganizationByID(ctx, pool.OrgID) if err != nil { return nil, errors.Wrap(err, "fetching org") @@ -922,7 +922,7 @@ func (r *Runner) getPoolManagerFromInstance(ctx context.Context, instance params if err != nil { return nil, errors.Wrapf(err, "fetching pool manager for org %s", pool.OrgName) } - } else if pool.EnterpriseID != "" { + case pool.EnterpriseID != "": enterprise, err := r.store.GetEnterpriseByID(ctx, pool.EnterpriseID) if err != nil { return nil, errors.Wrap(err, "fetching enterprise") diff --git a/test/integration/e2e/client.go b/test/integration/e2e/client.go index 2ab81695..db841983 100644 --- a/test/integration/e2e/client.go +++ b/test/integration/e2e/client.go @@ -4,10 +4,11 @@ import ( "log/slog" "net/url" - "github.com/cloudbase/garm/client" - "github.com/cloudbase/garm/params" "github.com/go-openapi/runtime" openapiRuntimeClient "github.com/go-openapi/runtime/client" + + "github.com/cloudbase/garm/client" + "github.com/cloudbase/garm/params" ) var ( @@ -16,18 +17,18 @@ var ( ) func InitClient(baseURL string) { - garmUrl, err := url.Parse(baseURL) + garmURL, err := url.Parse(baseURL) if err != nil { panic(err) } - apiPath, err := url.JoinPath(garmUrl.Path, client.DefaultBasePath) + apiPath, err := url.JoinPath(garmURL.Path, client.DefaultBasePath) if err != nil { panic(err) } transportCfg := client.DefaultTransportConfig(). - WithHost(garmUrl.Host). + WithHost(garmURL.Host). WithBasePath(apiPath). - WithSchemes([]string{garmUrl.Scheme}) + WithSchemes([]string{garmURL.Scheme}) cli = client.NewHTTPClientWithConfig(nil, transportCfg) } diff --git a/test/integration/e2e/client_utils.go b/test/integration/e2e/client_utils.go index 955f7b52..367ff76a 100644 --- a/test/integration/e2e/client_utils.go +++ b/test/integration/e2e/client_utils.go @@ -1,6 +1,8 @@ package e2e import ( + "github.com/go-openapi/runtime" + "github.com/cloudbase/garm/client" clientControllerInfo "github.com/cloudbase/garm/client/controller_info" clientCredentials "github.com/cloudbase/garm/client/credentials" @@ -14,7 +16,6 @@ import ( clientProviders "github.com/cloudbase/garm/client/providers" clientRepositories "github.com/cloudbase/garm/client/repositories" "github.com/cloudbase/garm/params" - "github.com/go-openapi/runtime" ) // /////////// diff --git a/test/integration/e2e/e2e.go b/test/integration/e2e/e2e.go index 0c0c27e2..516c1e10 100644 --- a/test/integration/e2e/e2e.go +++ b/test/integration/e2e/e2e.go @@ -44,7 +44,7 @@ func GetControllerInfo() *params.ControllerInfo { if err := appendCtrlInfoToGitHubEnv(&controllerInfo); err != nil { panic(err) } - if err := printJsonResponse(controllerInfo); err != nil { + if err := printJSONResponse(controllerInfo); err != nil { panic(err) } return &controllerInfo diff --git a/test/integration/e2e/instances.go b/test/integration/e2e/instances.go index 1200f3a3..f1a693ef 100644 --- a/test/integration/e2e/instances.go +++ b/test/integration/e2e/instances.go @@ -10,7 +10,7 @@ import ( ) func waitInstanceStatus(name string, status commonParams.InstanceStatus, runnerStatus params.RunnerStatus, timeout time.Duration) (*params.Instance, error) { - var timeWaited time.Duration = 0 + var timeWaited time.Duration // default is 0 var instance *params.Instance slog.Info("Waiting for instance to reach desired status", "instance", name, "desired_status", status, "desired_runner_status", runnerStatus) @@ -27,7 +27,7 @@ func waitInstanceStatus(name string, status commonParams.InstanceStatus, runnerS timeWaited += 5 * time.Second } - if err := printJsonResponse(*instance); err != nil { + if err := printJSONResponse(*instance); err != nil { return nil, err } return nil, fmt.Errorf("timeout waiting for instance %s status to reach status %s and runner status %s", name, status, runnerStatus) @@ -41,7 +41,7 @@ func DeleteInstance(name string, forceRemove bool) { } func WaitInstanceToBeRemoved(name string, timeout time.Duration) error { - var timeWaited time.Duration = 0 + var timeWaited time.Duration // default is 0 var instance *params.Instance slog.Info("Waiting for instance to be removed", "instance_name", name) @@ -52,9 +52,9 @@ func WaitInstanceToBeRemoved(name string, timeout time.Duration) error { } instance = nil - for _, i := range instances { - if i.Name == name { - instance = &i + for k, v := range instances { + if v.Name == name { + instance = &instances[k] break } } @@ -68,14 +68,14 @@ func WaitInstanceToBeRemoved(name string, timeout time.Duration) error { timeWaited += 5 * time.Second } - if err := printJsonResponse(*instance); err != nil { + if err := printJSONResponse(*instance); err != nil { return err } return fmt.Errorf("instance %s was not removed within the timeout", name) } func WaitPoolInstances(poolID string, status commonParams.InstanceStatus, runnerStatus params.RunnerStatus, timeout time.Duration) error { - var timeWaited time.Duration = 0 + var timeWaited time.Duration // default is 0 pool, err := getPool(cli, authToken, poolID) if err != nil { @@ -103,7 +103,7 @@ func WaitPoolInstances(poolID string, status commonParams.InstanceStatus, runner "runner_status", runnerStatus, "desired_instance_count", instancesCount, "pool_instance_count", len(poolInstances)) - if instancesCount == int(pool.MinIdleRunners) && instancesCount == len(poolInstances) { + if int(pool.MinIdleRunners) == len(poolInstances) { return nil } time.Sleep(5 * time.Second) diff --git a/test/integration/e2e/jobs.go b/test/integration/e2e/jobs.go index f3a1f3c6..bc93ff0a 100644 --- a/test/integration/e2e/jobs.go +++ b/test/integration/e2e/jobs.go @@ -54,7 +54,7 @@ func ValidateJobLifecycle(label string) { } func waitLabelledJob(label string, timeout time.Duration) (*params.Job, error) { - var timeWaited time.Duration = 0 + var timeWaited time.Duration // default is 0 var jobs params.Jobs var err error @@ -75,14 +75,14 @@ func waitLabelledJob(label string, timeout time.Duration) (*params.Job, error) { timeWaited += 5 * time.Second } - if err := printJsonResponse(jobs); err != nil { + if err := printJSONResponse(jobs); err != nil { return nil, err } return nil, fmt.Errorf("failed to wait job with label %s", label) } func waitJobStatus(id int64, status params.JobStatus, timeout time.Duration) (*params.Job, error) { - var timeWaited time.Duration = 0 + var timeWaited time.Duration // default is 0 var job *params.Job slog.Info("Waiting for job to reach status", "job_id", id, "status", status) @@ -93,9 +93,9 @@ func waitJobStatus(id int64, status params.JobStatus, timeout time.Duration) (*p } job = nil - for _, j := range jobs { - if j.ID == id { - job = &j + for k, v := range jobs { + if v.ID == id { + job = &jobs[k] break } } @@ -116,7 +116,7 @@ func waitJobStatus(id int64, status params.JobStatus, timeout time.Duration) (*p timeWaited += 5 * time.Second } - if err := printJsonResponse(*job); err != nil { + if err := printJSONResponse(*job); err != nil { return nil, err } return nil, fmt.Errorf("timeout waiting for job %d to reach status %s", id, status) diff --git a/test/integration/e2e/organizations.go b/test/integration/e2e/organizations.go index 8f511215..7a7d0e0d 100644 --- a/test/integration/e2e/organizations.go +++ b/test/integration/e2e/organizations.go @@ -116,7 +116,7 @@ func dumpOrgInstancesDetails(orgID string) error { if err != nil { return err } - if err := printJsonResponse(org); err != nil { + if err := printJSONResponse(org); err != nil { return err } @@ -132,7 +132,7 @@ func dumpOrgInstancesDetails(orgID string) error { return err } slog.Info("Instance info", "instance_name", instance.Name) - if err := printJsonResponse(instance); err != nil { + if err := printJSONResponse(instance); err != nil { return err } } diff --git a/test/integration/e2e/pools.go b/test/integration/e2e/pools.go index f00e07eb..b4371e29 100644 --- a/test/integration/e2e/pools.go +++ b/test/integration/e2e/pools.go @@ -9,7 +9,7 @@ import ( ) func waitPoolNoInstances(id string, timeout time.Duration) error { - var timeWaited time.Duration = 0 + var timeWaited time.Duration // default is 0 var pool *params.Pool var err error @@ -37,7 +37,7 @@ func dumpPoolInstancesDetails(poolID string) error { if err != nil { return err } - if err := printJsonResponse(pool); err != nil { + if err := printJSONResponse(pool); err != nil { return err } for _, instance := range pool.Instances { @@ -46,7 +46,7 @@ func dumpPoolInstancesDetails(poolID string) error { return err } slog.Info("Instance details", "instance_name", instance.Name) - if err := printJsonResponse(instanceDetails); err != nil { + if err := printJSONResponse(instanceDetails); err != nil { return err } } diff --git a/test/integration/e2e/repositories.go b/test/integration/e2e/repositories.go index b1e9236d..9366c728 100644 --- a/test/integration/e2e/repositories.go +++ b/test/integration/e2e/repositories.go @@ -126,7 +126,7 @@ func dumpRepoInstancesDetails(repoID string) error { if err != nil { return err } - if err := printJsonResponse(repo); err != nil { + if err := printJSONResponse(repo); err != nil { return err } @@ -142,7 +142,7 @@ func dumpRepoInstancesDetails(repoID string) error { return err } slog.Info("Instance info", "instance_name", instance.Name) - if err := printJsonResponse(instance); err != nil { + if err := printJSONResponse(instance); err != nil { return err } } diff --git a/test/integration/e2e/utils.go b/test/integration/e2e/utils.go index ed8c2d62..37e48fe4 100644 --- a/test/integration/e2e/utils.go +++ b/test/integration/e2e/utils.go @@ -5,7 +5,7 @@ import ( "log/slog" ) -func printJsonResponse(resp interface{}) error { +func printJSONResponse(resp interface{}) error { b, err := json.MarshalIndent(resp, "", " ") if err != nil { return err diff --git a/test/integration/gh_cleanup/main.go b/test/integration/gh_cleanup/main.go index b841652e..2c9c3735 100644 --- a/test/integration/gh_cleanup/main.go +++ b/test/integration/gh_cleanup/main.go @@ -16,16 +16,16 @@ var ( ) func main() { - controllerID, ctrlIdFound := os.LookupEnv("GARM_CONTROLLER_ID") - if ctrlIdFound { + controllerID, ctrlIDFound := os.LookupEnv("GARM_CONTROLLER_ID") + if ctrlIDFound { _ = e2e.GhOrgRunnersCleanup(ghToken, orgName, controllerID) _ = e2e.GhRepoRunnersCleanup(ghToken, orgName, repoName, controllerID) } else { slog.Warn("Env variable GARM_CONTROLLER_ID is not set, skipping GitHub runners cleanup") } - baseURL, baseUrlFound := os.LookupEnv("GARM_BASE_URL") - if ctrlIdFound && baseUrlFound { + baseURL, baseURLFound := os.LookupEnv("GARM_BASE_URL") + if ctrlIDFound && baseURLFound { webhookURL := fmt.Sprintf("%s/webhooks/%s", baseURL, controllerID) _ = e2e.GhOrgWebhookCleanup(ghToken, webhookURL, orgName) _ = e2e.GhRepoWebhookCleanup(ghToken, webhookURL, orgName, repoName) diff --git a/util/util.go b/util/util.go index bf70d081..4255dbf0 100644 --- a/util/util.go +++ b/util/util.go @@ -21,12 +21,12 @@ import ( "fmt" "net/http" - "github.com/cloudbase/garm/params" - "github.com/cloudbase/garm/runner/common" - "github.com/google/go-github/v57/github" "github.com/pkg/errors" "golang.org/x/oauth2" + + "github.com/cloudbase/garm/params" + "github.com/cloudbase/garm/runner/common" ) type githubClient struct { @@ -84,6 +84,8 @@ func GithubClient(ctx context.Context, token string, credsDetails params.GithubC return nil, nil, fmt.Errorf("failed to parse CA cert") } } + // nolint:golangci-lint,gosec,godox + // TODO: set TLS MinVersion httpTransport := &http.Transport{ TLSClientConfig: &tls.Config{ RootCAs: roots, diff --git a/websocket/client.go b/websocket/client.go index ef420460..69812a0d 100644 --- a/websocket/client.go +++ b/websocket/client.go @@ -5,7 +5,6 @@ import ( "time" "github.com/google/uuid" - "github.com/gorilla/websocket" )