diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index c1d42b0c..93c3b5aa 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -24,14 +24,14 @@ jobs: uses: golangci/golangci-lint-action@v9 with: # Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version - version: v2.1.0 + version: v2.6.2 # Optional: working directory, useful for monorepos # working-directory: somedir # Optional: golangci-lint command line arguments. # args: --issues-exit-code=0 - args: --config ./golangcilint.yaml --build-tags debug,needprivileges,sync,scrub,search,userprefs,metrics,lint,mgmt,imagetrust ./cmd/... ./pkg/... + args: --build-tags debug,needprivileges,sync,scrub,search,userprefs,metrics,lint,mgmt,imagetrust ./cmd/... ./pkg/... # Optional: show only new issues if it's a pull request. The default value is `false`. # only-new-issues: true diff --git a/golangcilint.yaml b/.golangci.yaml similarity index 87% rename from golangcilint.yaml rename to .golangci.yaml index 5ba1a568..94f2b1ba 100644 --- a/golangcilint.yaml +++ b/.golangci.yaml @@ -19,6 +19,7 @@ linters: - maintidx - mnd - musttag + - noinlineerr - paralleltest - promlinter - protogetter @@ -29,6 +30,7 @@ linters: - staticcheck - usetesting - wrapcheck + - wsl settings: cyclop: max-complexity: 40 @@ -68,9 +70,20 @@ linters: - l *ldap.Conn - w http.ResponseWriter - r *http.Request - wsl: - allow-assign-and-anything: true - force-err-cuddling: true + wsl_v5: + allow-first-in-block: true + allow-whole-block: false + branch-max-lines: 2 + enable: + - err + disable: + - assign + - defer + - if + - send + - expr + - select + - switch exclusions: generated: lax presets: diff --git a/Makefile b/Makefile index d80314b3..3bc1f54b 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ TOOLSDIR := $(shell pwd)/hack/tools PATH := bin:$(TOOLSDIR)/bin:$(PATH) STACKER := $(shell which stacker) GOLINTER := $(TOOLSDIR)/bin/golangci-lint -GOLINTER_VERSION := v2.1.0 +GOLINTER_VERSION := v2.6.2 NOTATION := $(TOOLSDIR)/bin/notation NOTATION_VERSION := 1.3.2 COSIGN := $(TOOLSDIR)/bin/cosign @@ -331,10 +331,14 @@ covhtml: gocovmerge coverage*.txt > coverage.txt go tool cover -html=coverage.txt -o coverage.html -$(GOLINTER): +$(GOLINTER): $(TOOLSDIR)/.golangci-lint-$(GOLINTER_VERSION) + +$(TOOLSDIR)/.golangci-lint-$(GOLINTER_VERSION): mkdir -p $(TOOLSDIR)/bin + rm -f $(TOOLSDIR)/.golangci-lint-* curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(TOOLSDIR)/bin $(GOLINTER_VERSION) $(GOLINTER) version + touch $@ .PHONY: check-logs check-logs: @@ -342,13 +346,14 @@ check-logs: .PHONY: check check: $(if $(findstring ui,$(BUILD_LABELS)), ui) -check: ./golangcilint.yaml $(GOLINTER) +check: ./.golangci.yaml $(GOLINTER) mkdir -p pkg/extensions/build; touch pkg/extensions/build/.empty - $(GOLINTER) --config ./golangcilint.yaml run --output.text.colors --build-tags ./... - $(GOLINTER) --config ./golangcilint.yaml run --output.text.colors --build-tags $(BUILD_LABELS) ./... - $(GOLINTER) --config ./golangcilint.yaml run --output.text.colors --build-tags debug ./pkg/debug/swagger/ ./pkg/debug/gqlplayground - $(GOLINTER) --config ./golangcilint.yaml run --output.text.colors --build-tags dev ./pkg/test/inject/ - $(GOLINTER) --config ./golangcilint.yaml run --output.text.colors --build-tags stress ./pkg/cli/server/ + $(GOLINTER) run --output.text.colors --build-tags ./... + $(GOLINTER) run --output.text.colors --build-tags $(BUILD_LABELS) ./... + $(GOLINTER) run --output.text.colors --build-tags debug ./pkg/debug/swagger/ ./pkg/debug/gqlplayground + $(GOLINTER) run --output.text.colors --build-tags dev ./pkg/test/inject/ + $(GOLINTER) run --output.text.colors --build-tags stress ./pkg/cli/server/ + $(GOLINTER) run --output.text.colors --build-tags needprivileges,$(BUILD_LABELS) ./pkg/cli/client/ ./pkg/storage/local/ ./pkg/api/config/ rm pkg/extensions/build/.empty .PHONY: swagger diff --git a/cmd/zb/helper.go b/cmd/zb/helper.go index bc8f6b5d..1a8cbd74 100644 --- a/cmd/zb/helper.go +++ b/cmd/zb/helper.go @@ -25,7 +25,7 @@ import ( "zotregistry.dev/zot/v2/pkg/common" ) -func makeHTTPGetRequest(url string, resultPtr interface{}, client *resty.Client) (http.Header, error) { +func makeHTTPGetRequest(url string, resultPtr any, client *resty.Client) (http.Header, error) { resp, err := client.R().Get(url) if err != nil { return http.Header{}, err diff --git a/cmd/zb/main.go b/cmd/zb/main.go index ca69e96d..d0840d03 100644 --- a/cmd/zb/main.go +++ b/cmd/zb/main.go @@ -10,7 +10,7 @@ import ( "zotregistry.dev/zot/v2/pkg/log" ) -// "zb" - performance benchmark and stress. +// NewPerfRootCmd creates the root command for "zb" - performance benchmark and stress. func NewPerfRootCmd() *cobra.Command { showVersion := false diff --git a/cmd/zb/perf.go b/cmd/zb/perf.go index 08633c08..d8442dde 100644 --- a/cmd/zb/perf.go +++ b/cmd/zb/perf.go @@ -196,10 +196,10 @@ func updateStats(summary *statsSummary, record statsRecord) { } type cicdTestSummary struct { - Name string `json:"name"` - Unit string `json:"unit"` - Value interface{} `json:"value"` - Range string `json:"range,omitempty"` + Name string `json:"name"` + Unit string `json:"unit"` + Value any `json:"value"` + Range string `json:"range,omitempty"` } type manifestStruct struct { @@ -299,7 +299,7 @@ func GetCatalog( statusRequests = sync.Map{} - for count := 0; count < requests; count++ { + for range requests { // Push random blob _, repos, err = pushMonolithImage(workdir, url, repo, repos, config, client) if err != nil { @@ -307,7 +307,7 @@ func GetCatalog( } } - for count := 0; count < requests; count++ { + for range requests { func() { start := time.Now() @@ -376,7 +376,7 @@ func PushMonolithStreamed( statusRequests = sync.Map{} } - for count := 0; count < requests; count++ { + for count := range requests { repos = pushMonolithAndCollect(workdir, url, trepo, count, repos, config, client, statsCh) } @@ -406,7 +406,7 @@ func PushChunkStreamed( statusRequests = sync.Map{} } - for count := 0; count < requests; count++ { + for count := range requests { repos = pushChunkAndCollect(workdir, url, trepo, count, repos, config, client, statsCh) } @@ -493,7 +493,7 @@ func Pull( } // download image - for count := 0; count < requests; count++ { + for range requests { repos = pullAndCollect(url, repos, manifestItem, config, client, statsCh) } @@ -530,7 +530,7 @@ func MixedPullAndPush( manifestHash: manifestHash, } - for count := 0; count < requests; count++ { + for count := range requests { idx := flipFunc(config.probabilityRange) readTestIdx := 0 @@ -667,6 +667,16 @@ func Perf( outFmt string, srcIPs string, srcCIDR string, skipCleanup bool, ) { json := jsoniter.ConfigCompatibleWithStandardLibrary + + // fatalWithCleanup calls teardown then logs fatal, ensuring cleanup happens before exit. + // Uses sync.Once to ensure teardown is only called once, even from goroutines. + var teardownOnce sync.Once + fatalWithCleanup := func(err error) { + teardownOnce.Do(func() { + teardown(workdir) + }) + log.Fatal(err) + } // logging log.SetFlags(0) log.SetOutput(tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.TabIndent)) @@ -694,7 +704,6 @@ func Perf( log.Printf("Preparing test data ...\n") setup(workdir) - defer teardown(workdir) log.Printf("Starting tests ...\n") @@ -709,7 +718,7 @@ func Perf( } else if len(srcCIDR) > 0 { ips, err = getIPsFromCIDR(srcCIDR, maxSourceIPs) if err != nil { - log.Fatal(err) //nolint: gocritic + fatalWithCleanup(err) } } @@ -722,7 +731,7 @@ func Perf( start := time.Now() - for c := 0; c < concurrency; c++ { + for range concurrency { // parallelize with clients wg.Add(1) @@ -731,12 +740,12 @@ func Perf( httpClient, err := getRandomClientIPs(auth, url, ips) if err != nil { - log.Fatal(err) + fatalWithCleanup(err) } err = tconfig.tfunc(workdir, url, repo, requests/concurrency, tconfig, statsCh, httpClient, skipCleanup) if err != nil { - log.Fatal(err) + fatalWithCleanup(err) } }() } @@ -754,7 +763,7 @@ func Perf( summary.mixedType = true } - for count := 0; count < requests; count++ { + for range requests { record := <-statsCh updateStats(&summary, record) } @@ -771,14 +780,19 @@ func Perf( if outFmt == cicdFmt { jsonOut, err := json.Marshal(cicdSummary) if err != nil { - log.Fatal(err) // file closed on exit + fatalWithCleanup(err) } if err := os.WriteFile(outFmt+".json", jsonOut, defaultFilePerms); err != nil { - log.Fatal(err) + fatalWithCleanup(err) } } + // Cleanup before exit (sync.Once ensures it only runs once, even if fatalWithCleanup was called) + teardownOnce.Do(func() { + teardown(workdir) + }) + if zbError { os.Exit(1) } diff --git a/cmd/zli/main.go b/cmd/zli/main.go index 1a633d1b..084e6741 100644 --- a/cmd/zli/main.go +++ b/cmd/zli/main.go @@ -1,5 +1,4 @@ //go:build search -// +build search package main diff --git a/cmd/zli/main_test.go b/cmd/zli/main_test.go index a38bd515..5f9688f6 100644 --- a/cmd/zli/main_test.go +++ b/cmd/zli/main_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package main_test diff --git a/cmd/zxp/main.go b/cmd/zxp/main.go index e14940aa..4678dfd8 100644 --- a/cmd/zxp/main.go +++ b/cmd/zxp/main.go @@ -1,5 +1,4 @@ //go:build !metrics -// +build !metrics package main diff --git a/pkg/api/authn.go b/pkg/api/authn.go index e643d142..d7681552 100644 --- a/pkg/api/authn.go +++ b/pkg/api/authn.go @@ -13,6 +13,7 @@ import ( "net" "net/http" "os" + "slices" "strconv" "strings" "time" @@ -657,7 +658,7 @@ func getRelyingPartyArgs(cfg *config.Config, provider string, hashKey, encryptKe scopes := providerConfig.Scopes // openid scope must be the first one in list - if !zcommon.Contains(scopes, oidc.ScopeOpenID) && config.IsOpenIDSupported(provider) { + if !slices.Contains(scopes, oidc.ScopeOpenID) && config.IsOpenIDSupported(provider) { scopes = append([]string{oidc.ScopeOpenID}, scopes...) } diff --git a/pkg/api/authn_test.go b/pkg/api/authn_test.go index acd5ff27..2cb91da6 100644 --- a/pkg/api/authn_test.go +++ b/pkg/api/authn_test.go @@ -1,5 +1,4 @@ //go:build mgmt -// +build mgmt package api_test @@ -52,6 +51,7 @@ const ( type ( apiKeyResponse struct { mTypes.APIKeyDetails + APIKey string `json:"apiKey"` } ) @@ -1398,6 +1398,7 @@ func TestRedisCookieStore(t *testing.T) { type mockUUIDGenerator struct { guuid.Generator + succeedAttempts int attemptCount int } diff --git a/pkg/api/authz.go b/pkg/api/authz.go index 0c6475fa..fba44f6d 100644 --- a/pkg/api/authz.go +++ b/pkg/api/authz.go @@ -3,6 +3,7 @@ package api import ( "context" "net/http" + "slices" glob "github.com/bmatcuk/doublestar/v4" "github.com/gorilla/mux" @@ -67,19 +68,19 @@ func (ac *AccessController) getGlobPatterns(username string, groups []string, ac for pattern, policyGroup := range ac.Config.Repositories { if username == "" { // check anonymous policy - if common.Contains(policyGroup.AnonymousPolicy, action) { + if slices.Contains(policyGroup.AnonymousPolicy, action) { globPatterns[pattern] = true } } else { // check default policy (authenticated user) - if common.Contains(policyGroup.DefaultPolicy, action) { + if slices.Contains(policyGroup.DefaultPolicy, action) { globPatterns[pattern] = true } } // check user based policy for _, p := range policyGroup.Policies { - if common.Contains(p.Users, username) && common.Contains(p.Actions, action) { + if slices.Contains(p.Users, username) && slices.Contains(p.Actions, action) { globPatterns[pattern] = true } } @@ -87,7 +88,7 @@ func (ac *AccessController) getGlobPatterns(username string, groups []string, ac // check group based policy for _, group := range groups { for _, p := range policyGroup.Policies { - if common.Contains(p.Groups, group) && common.Contains(p.Actions, action) { + if slices.Contains(p.Groups, group) && slices.Contains(p.Actions, action) { globPatterns[pattern] = true } } @@ -131,7 +132,7 @@ func (ac *AccessController) can(userAc *reqCtx.UserAccessControl, action, reposi // check admins based policy if !can { adminPolicy := ac.Config.GetAdminPolicy() - if ac.isAdmin(username, userGroups) && common.Contains(adminPolicy.Actions, action) { + if ac.isAdmin(username, userGroups) && slices.Contains(adminPolicy.Actions, action) { can = true } } @@ -142,7 +143,7 @@ func (ac *AccessController) can(userAc *reqCtx.UserAccessControl, action, reposi // isAdmin . func (ac *AccessController) isAdmin(username string, userGroups []string) bool { adminPolicy := ac.Config.GetAdminPolicy() - if common.Contains(adminPolicy.Users, username) || ac.isAnyGroupInAdminPolicy(userGroups) { + if slices.Contains(adminPolicy.Users, username) || ac.isAnyGroupInAdminPolicy(userGroups) { return true } @@ -151,13 +152,10 @@ func (ac *AccessController) isAdmin(username string, userGroups []string) bool { func (ac *AccessController) isAnyGroupInAdminPolicy(userGroups []string) bool { adminPolicy := ac.Config.GetAdminPolicy() - for _, group := range userGroups { - if common.Contains(adminPolicy.Groups, group) { - return true - } - } - return false + return slices.ContainsFunc(userGroups, func(group string) bool { + return slices.Contains(adminPolicy.Groups, group) + }) } func (ac *AccessController) getUserGroups(username string) []string { @@ -218,16 +216,16 @@ func (ac *AccessController) isPermitted(userGroups []string, username, action st ) bool { // check repo/system based policies for _, p := range policyGroup.Policies { - if common.Contains(p.Users, username) && common.Contains(p.Actions, action) { + if slices.Contains(p.Users, username) && slices.Contains(p.Actions, action) { return true } } if userGroups != nil { for _, p := range policyGroup.Policies { - if common.Contains(p.Actions, action) { + if slices.Contains(p.Actions, action) { for _, group := range p.Groups { - if common.Contains(userGroups, group) { + if slices.Contains(userGroups, group) { return true } } @@ -236,12 +234,12 @@ func (ac *AccessController) isPermitted(userGroups []string, username, action st } // check defaultPolicy - if common.Contains(policyGroup.DefaultPolicy, action) && username != "" { + if slices.Contains(policyGroup.DefaultPolicy, action) && username != "" { return true } // check anonymousPolicy - if common.Contains(policyGroup.AnonymousPolicy, action) && username == "" { + if slices.Contains(policyGroup.AnonymousPolicy, action) && username == "" { return true } @@ -348,7 +346,7 @@ func DistSpecAuthzHandler(ctlr *Controller) mux.MiddlewareFunc { is := ctlr.StoreController.GetImageStore(resource) tags, err := is.GetImageTags(resource) - if err == nil && common.Contains(tags, reference) && reference != "latest" { + if err == nil && slices.Contains(tags, reference) && reference != "latest" { // if repo exists and request's tag exists then action is UPDATE action = constants.UpdatePermission } @@ -404,7 +402,7 @@ func MetricsAuthzHandler(ctlr *Controller) mux.MiddlewareFunc { } username := userAc.GetUsername() - if !common.Contains(metricsConfig.Users, username) { + if !slices.Contains(metricsConfig.Users, username) { common.AuthzFail(response, request, username, realm, failDelay) return diff --git a/pkg/api/bearer.go b/pkg/api/bearer.go index 824459f1..c2f9d669 100644 --- a/pkg/api/bearer.go +++ b/pkg/api/bearer.go @@ -31,8 +31,9 @@ type ResourceAction struct { // authentication specification, in addition to the standard registered claims. // https://distribution.github.io/distribution/spec/auth/jwt/ type ClaimsWithAccess struct { - Access []ResourceAccess `json:"access"` jwt.RegisteredClaims + + Access []ResourceAccess `json:"access"` } type AuthChallengeError struct { @@ -91,7 +92,7 @@ func (a *BearerAuthorizer) Authorize(header string, requested *ResourceAction) e signedString := bearerTokenMatch.ReplaceAllString(header, "$1") - token, err := jwt.ParseWithClaims(signedString, &ClaimsWithAccess{}, func(token *jwt.Token) (interface{}, error) { + token, err := jwt.ParseWithClaims(signedString, &ClaimsWithAccess{}, func(token *jwt.Token) (any, error) { return a.key, nil }, jwt.WithValidMethods(a.allowedSigningAlgorithms()), jwt.WithIssuedAt()) if err != nil { diff --git a/pkg/api/config/config.go b/pkg/api/config/config.go index a0d55502..12f305fd 100644 --- a/pkg/api/config/config.go +++ b/pkg/api/config/config.go @@ -2,6 +2,7 @@ package config import ( "encoding/json" + "maps" "os" "sync" "time" @@ -34,8 +35,8 @@ type StorageConfig struct { GCDelay time.Duration // applied for blobs GCInterval time.Duration Retention ImageRetention - StorageDriver map[string]interface{} `mapstructure:",omitempty"` - CacheDriver map[string]interface{} `mapstructure:",omitempty"` + StorageDriver map[string]any `mapstructure:",omitempty"` + CacheDriver map[string]any `mapstructure:",omitempty"` // GCMaxSchedulerDelay is the maximum random delay for GC task scheduling // This field is not configurable by the end user @@ -210,7 +211,7 @@ type SchedulerConfig struct { NumWorkers int } -// contains the scale-out configuration which is identical for all zot replicas. +// ClusterConfig contains the scale-out configuration which is identical for all zot replicas. type ClusterConfig struct { // contains the "host:port" of all the zot instances participating // in the cluster. @@ -305,7 +306,8 @@ type LogConfig struct { type GlobalStorageConfig struct { StorageConfig `mapstructure:",squash"` - SubPaths map[string]StorageConfig + + SubPaths map[string]StorageConfig } type AccessControlConfig struct { @@ -377,9 +379,7 @@ func (config *AccessControlConfig) GetRepositories() Repositories { // Return a copy to avoid race conditions reposCopy := make(Repositories) - for k, v := range config.Repositories { - reposCopy[k] = v - } + maps.Copy(reposCopy, config.Repositories) return reposCopy } @@ -410,9 +410,7 @@ func (config *AccessControlConfig) GetGroups() Groups { // Return a copy to avoid race conditions groupsCopy := make(Groups) - for k, v := range config.Groups { - groupsCopy[k] = v - } + maps.Copy(groupsCopy, config.Groups) return groupsCopy } @@ -1101,7 +1099,7 @@ func SameFile(str1, str2 string) (bool, error) { } // DeepCopy performs a deep copy of src into dst using JSON marshaling/unmarshaling. -func DeepCopy(src, dst interface{}) error { +func DeepCopy(src, dst any) error { bytes, err := json.Marshal(src) if err != nil { return err diff --git a/pkg/api/config/config_elevated_test.go b/pkg/api/config/config_elevated_test.go index e437cf24..134982a0 100644 --- a/pkg/api/config/config_elevated_test.go +++ b/pkg/api/config/config_elevated_test.go @@ -1,5 +1,4 @@ //go:build needprivileges -// +build needprivileges package config_test diff --git a/pkg/api/config/config_test.go b/pkg/api/config/config_test.go index 2712935f..ee5e912a 100644 --- a/pkg/api/config/config_test.go +++ b/pkg/api/config/config_test.go @@ -1265,10 +1265,10 @@ func TestConfig(t *testing.T) { }, }, }, - StorageDriver: map[string]interface{}{ + StorageDriver: map[string]any{ "type": "filesystem", }, - CacheDriver: map[string]interface{}{ + CacheDriver: map[string]any{ "type": "redis", }, }, @@ -1282,7 +1282,7 @@ func TestConfig(t *testing.T) { }, }, }, - StorageDriver: map[string]interface{}{ + StorageDriver: map[string]any{ "type": "s3", }, }, diff --git a/pkg/api/config/redis/redis.go b/pkg/api/config/redis/redis.go index f185c90f..ab7b3d26 100644 --- a/pkg/api/config/redis/redis.go +++ b/pkg/api/config/redis/redis.go @@ -20,11 +20,11 @@ type RedisLogger struct { Log log.Logger } -func (r RedisLogger) Printf(ctx context.Context, format string, v ...interface{}) { +func (r RedisLogger) Printf(ctx context.Context, format string, v ...any) { r.Log.Debug().Msgf(format, v...) } -func GetRedisClient(redisConfig map[string]interface{}, log log.Logger) (redis.UniversalClient, error) { +func GetRedisClient(redisConfig map[string]any, log log.Logger) (redis.UniversalClient, error) { once.Do(func() { redis.SetLogger(RedisLogger{log}) }) // call redis.SetLogger only once // go-redis supports connecting via the redis uri specification (more convenient than parameter parsing) @@ -59,11 +59,11 @@ func GetRedisClient(redisConfig map[string]interface{}, log log.Logger) (redis.U return redis.NewUniversalClient(opts), nil } -func ParseRedisUniversalOptions(redisConfig map[string]interface{}, //nolint: gocyclo +func ParseRedisUniversalOptions(redisConfig map[string]any, //nolint: gocyclo log log.Logger, ) *redis.UniversalOptions { opts := redis.UniversalOptions{} - sanitizedConfig := map[string]interface{}{} + sanitizedConfig := map[string]any{} for key, val := range redisConfig { if key == "password" || key == "sentinel_password" { @@ -206,7 +206,7 @@ func ParseRedisUniversalOptions(redisConfig map[string]interface{}, //nolint: go return &opts } -func logCastWarning(key string, value interface{}, hideValue bool, log log.Logger) { +func logCastWarning(key string, value any, hideValue bool, log log.Logger) { if hideValue { log.Warn().Str("key", key).Msg("failed to cast parameter to intended type") } else { @@ -214,7 +214,7 @@ func logCastWarning(key string, value interface{}, hideValue bool, log log.Logge } } -func getBool(dict map[string]interface{}, key string, log log.Logger) (bool, bool) { +func getBool(dict map[string]any, key string, log log.Logger) (bool, bool) { value, ok := dict[key] if !ok { return false, false @@ -230,7 +230,7 @@ func getBool(dict map[string]interface{}, key string, log log.Logger) (bool, boo return ret, true } -func getInt(dict map[string]interface{}, key string, log log.Logger) (int, bool) { +func getInt(dict map[string]any, key string, log log.Logger) (int, bool) { value, ok := dict[key] if !ok { return 0, false @@ -246,7 +246,7 @@ func getInt(dict map[string]interface{}, key string, log log.Logger) (int, bool) return ret, true } -func GetString(dict map[string]interface{}, key string, hideValue bool, log log.Logger) (string, bool) { +func GetString(dict map[string]any, key string, hideValue bool, log log.Logger) (string, bool) { value, ok := dict[key] if !ok { return "", false @@ -262,7 +262,7 @@ func GetString(dict map[string]interface{}, key string, hideValue bool, log log. return ret, true } -func getStringSlice(dict map[string]interface{}, key string, log log.Logger) ([]string, bool) { +func getStringSlice(dict map[string]any, key string, log log.Logger) ([]string, bool) { value, ok := dict[key] if !ok { return []string{}, false @@ -278,7 +278,7 @@ func getStringSlice(dict map[string]interface{}, key string, log log.Logger) ([] return ret, true } -func getDuration(dict map[string]interface{}, key string, log log.Logger) (time.Duration, bool) { +func getDuration(dict map[string]any, key string, log log.Logger) (time.Duration, bool) { value, ok := dict[key] if !ok { return 0, false diff --git a/pkg/api/config/redis/redis_test.go b/pkg/api/config/redis/redis_test.go index ff57b765..cf227ef2 100644 --- a/pkg/api/config/redis/redis_test.go +++ b/pkg/api/config/redis/redis_test.go @@ -42,38 +42,38 @@ func TestRedisOptions(t *testing.T) { Convey("Test redis url parsing", func() { // Errors - config := map[string]interface{}{"url": false} + config := map[string]any{"url": false} clientIntf, err := rediscfg.GetRedisClient(config, log) So(err, ShouldNotBeNil) So(clientIntf, ShouldBeNil) - config = map[string]interface{}{"url": ""} + config = map[string]any{"url": ""} clientIntf, err = rediscfg.GetRedisClient(config, log) So(err, ShouldNotBeNil) So(clientIntf, ShouldBeNil) - config = map[string]interface{}{"url": "qwerty@localhost:6379/1?dial_timeout=5s"} + config = map[string]any{"url": "qwerty@localhost:6379/1?dial_timeout=5s"} clientIntf, err = rediscfg.GetRedisClient(config, log) So(err, ShouldNotBeNil) So(clientIntf, ShouldBeNil) - config = map[string]interface{}{"url": "http://:qwerty@localhost:6379/1?dial_timeout=5s"} + config = map[string]any{"url": "http://:qwerty@localhost:6379/1?dial_timeout=5s"} clientIntf, err = rediscfg.GetRedisClient(config, log) So(err, ShouldNotBeNil) So(clientIntf, ShouldBeNil) - config = map[string]interface{}{"url": "http://localhost:6379/1?addr=host2:6379&addr=host1:6379"} + config = map[string]any{"url": "http://localhost:6379/1?addr=host2:6379&addr=host1:6379"} clientIntf, err = rediscfg.GetRedisClient(config, log) So(err, ShouldNotBeNil) So(clientIntf, ShouldBeNil) // Success - config = map[string]interface{}{"url": "redis://user:password@localhost:6379/1?dial_timeout=5s"} + config = map[string]any{"url": "redis://user:password@localhost:6379/1?dial_timeout=5s"} clientIntf, err = rediscfg.GetRedisClient(config, log) So(err, ShouldBeNil) @@ -82,7 +82,7 @@ func TestRedisOptions(t *testing.T) { _, ok := clientIntf.(*redis.Client) So(ok, ShouldBeTrue) - config = map[string]interface{}{"url": "redis://user:password@host1:6379?addr=host2:6379&addr=host1:6379"} + config = map[string]any{"url": "redis://user:password@host1:6379?addr=host2:6379&addr=host1:6379"} clientIntf, err = rediscfg.GetRedisClient(config, log) So(err, ShouldBeNil) @@ -93,7 +93,7 @@ func TestRedisOptions(t *testing.T) { }) Convey("Test empty redis options from struct successfully", func() { - config := map[string]interface{}{} + config := map[string]any{} // All attributes will have zero values options := rediscfg.ParseRedisUniversalOptions(config, log) @@ -139,7 +139,7 @@ func TestRedisOptions(t *testing.T) { }) Convey("Test redis options from struct successfully", func() { - config := map[string]interface{}{ + config := map[string]any{ "addr": []string{ "a.repo:26379", "b.repo:26379", @@ -221,7 +221,7 @@ func TestRedisOptions(t *testing.T) { }) Convey("Test redis options from struct with warnings", func() { - config := map[string]interface{}{ + config := map[string]any{ "addr": map[string]int{}, "db": "somestring", "master_name": map[string]int{}, diff --git a/pkg/api/constants/consts.go b/pkg/api/constants/consts.go index 5afe00a9..a9896012 100644 --- a/pkg/api/constants/consts.go +++ b/pkg/api/constants/consts.go @@ -23,17 +23,19 @@ const ( APIKeysPrefix = "zak_" CallbackUIQueryParam = "callback_ui" APIKeyTimeFormat = time.RFC3339 - // authz permissions. - // method actions. + // CreatePermission is an authz permission for create actions. CreatePermission = "create" - ReadPermission = "read" + // ReadPermission is an authz permission for read actions. + ReadPermission = "read" + // UpdatePermission is an authz permission for update actions. UpdatePermission = "update" + // DeletePermission is an authz permission for delete actions. DeletePermission = "delete" - // behaviour actions. + // DetectManifestCollisionPermission is a behaviour action. DetectManifestCollisionPermission = "detectManifestCollision" - // zot scale-out hop count header. + // ScaleOutHopCountHeader is the zot scale-out hop count header. ScaleOutHopCountHeader = "X-Zot-Cluster-Hop-Count" - // log string keys. - // these can be used together with the logger to add context to a log message. + // RepositoryLogKey is a log string key. + // These can be used together with the logger to add context to a log message. RepositoryLogKey = "repository" ) diff --git a/pkg/api/constants/extensions.go b/pkg/api/constants/extensions.go index 188c4f55..cc4f6e02 100644 --- a/pkg/api/constants/extensions.go +++ b/pkg/api/constants/extensions.go @@ -7,21 +7,21 @@ const ( BaseExtension = "_zot" - // zot specific extensions. + // BasePrefix is a zot specific extension. BasePrefix = "/_zot" ExtPrefix = BasePrefix + "/ext" - // search extension. + // ExtSearch is the search extension. ExtSearch = "/search" ExtSearchPrefix = ExtPrefix + ExtSearch FullSearchPrefix = RoutePrefix + ExtSearchPrefix - // mgmt extension. + // Mgmt is the mgmt extension. Mgmt = "/mgmt" ExtMgmt = ExtPrefix + Mgmt FullMgmt = RoutePrefix + ExtMgmt - // signatures extension. + // Notation is the signatures extension. Notation = "/notation" ExtNotation = ExtPrefix + Notation FullNotation = RoutePrefix + ExtNotation @@ -29,7 +29,7 @@ const ( ExtCosign = ExtPrefix + Cosign FullCosign = RoutePrefix + ExtCosign - // user preferences extension. + // UserPrefs is the user preferences extension. UserPrefs = "/userprefs" ExtUserPrefs = ExtPrefix + UserPrefs FullUserPrefs = RoutePrefix + ExtUserPrefs diff --git a/pkg/api/controller.go b/pkg/api/controller.go index d42dce0f..524d3be6 100644 --- a/pkg/api/controller.go +++ b/pkg/api/controller.go @@ -178,7 +178,7 @@ func (c *Controller) Run() error { c.Server = server // Create the listener - listener, err := net.Listen("tcp", addr) + listener, err := net.Listen("tcp", addr) //nolint: noctx if err != nil { return err } @@ -457,7 +457,7 @@ func (c *Controller) Shutdown() { } } -// Will stop scheduler and wait for all tasks to finish their work. +// StopBackgroundTasks will stop scheduler and wait for all tasks to finish their work. func (c *Controller) StopBackgroundTasks() { if c.taskScheduler != nil { c.taskScheduler.Shutdown() diff --git a/pkg/api/controller_test.go b/pkg/api/controller_test.go index 8486c9c8..bd6fe851 100644 --- a/pkg/api/controller_test.go +++ b/pkg/api/controller_test.go @@ -1,5 +1,4 @@ //go:build sync && scrub && metrics && search && lint && userprefs && mgmt && imagetrust && ui -// +build sync,scrub,metrics,search,lint,userprefs,mgmt,imagetrust,ui package api_test @@ -176,7 +175,7 @@ func TestCreateCacheDatabaseDriver(t *testing.T) { conf.Storage.RemoteCache = true // test error on invalid redis client config - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "redis", "url": false, } @@ -186,13 +185,13 @@ func TestCreateCacheDatabaseDriver(t *testing.T) { So(driver, ShouldBeNil) // test valid redis client config - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "redis", "url": "redis://" + miniRedis.Addr(), } // test initialization for S3 storage - conf.Storage.StorageDriver = map[string]interface{}{ + conf.Storage.StorageDriver = map[string]any{ "name": "s3", "rootdirectory": "/zot", "url": "us-east-2", @@ -223,7 +222,7 @@ func TestCreateCacheDatabaseDriver(t *testing.T) { conf.Storage.RootDirectory = dir conf.Storage.Dedupe = true conf.Storage.RemoteCache = true - conf.Storage.StorageDriver = map[string]interface{}{ + conf.Storage.StorageDriver = map[string]any{ "name": "s3", "rootdirectory": "/zot", "region": "us-east-2", @@ -235,7 +234,7 @@ func TestCreateCacheDatabaseDriver(t *testing.T) { endpoint := os.Getenv("DYNAMODBMOCK_ENDPOINT") // missing cachetablename key - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "dynamodb", "endpoint": endpoint, "region": "us-east-2", @@ -246,7 +245,7 @@ func TestCreateCacheDatabaseDriver(t *testing.T) { So(driver, ShouldBeNil) // invalid cachetablename type - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "dynamodb", "endpoint": endpoint, "region": "us-east-2", @@ -257,7 +256,7 @@ func TestCreateCacheDatabaseDriver(t *testing.T) { So(err, ShouldNotBeNil) So(driver, ShouldBeNil) - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "dynamodb", "endpoint": endpoint, "region": "us-east-2", @@ -275,7 +274,7 @@ func TestCreateCacheDatabaseDriver(t *testing.T) { // negative test cases - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "endpoint": endpoint, "region": "us-east-2", "cachetablename": "BlobTable", @@ -290,7 +289,7 @@ func TestCreateCacheDatabaseDriver(t *testing.T) { So(err, ShouldBeNil) So(driver, ShouldBeNil) - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "dummy", "endpoint": endpoint, "region": "us-east-2", @@ -316,7 +315,7 @@ func TestCreateMetaDBDriver(t *testing.T) { conf.Storage.RootDirectory = dir conf.Storage.Dedupe = true conf.Storage.RemoteCache = true - conf.Storage.StorageDriver = map[string]interface{}{ + conf.Storage.StorageDriver = map[string]any{ "name": "s3", "rootdirectory": "/zot", "region": "us-east-2", @@ -325,7 +324,7 @@ func TestCreateMetaDBDriver(t *testing.T) { "skipverify": false, } - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "dummy", "endpoint": "http://localhost:4566", "region": "us-east-2", @@ -340,7 +339,7 @@ func TestCreateMetaDBDriver(t *testing.T) { So(err, ShouldNotBeNil) So(metaDB, ShouldBeNil) - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "dynamodb", "endpoint": "http://localhost:4566", "region": "us-east-2", @@ -354,7 +353,7 @@ func TestCreateMetaDBDriver(t *testing.T) { testFunc := func() { _, _ = meta.New(conf.Storage.StorageConfig, log) } So(testFunc, ShouldPanic) - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "dynamodb", "endpoint": "http://localhost:4566", "region": "us-east-2", @@ -369,7 +368,7 @@ func TestCreateMetaDBDriver(t *testing.T) { testFunc = func() { _, _ = meta.New(conf.Storage.StorageConfig, log) } So(testFunc, ShouldPanic) - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "dynamodb", "endpoint": "http://localhost:4566", "region": "us-east-2", @@ -395,7 +394,7 @@ func TestCreateMetaDBDriver(t *testing.T) { conf.Storage.RootDirectory = dir conf.Storage.Dedupe = true conf.Storage.RemoteCache = true - conf.Storage.StorageDriver = map[string]interface{}{ + conf.Storage.StorageDriver = map[string]any{ "name": "s3", "rootdirectory": "/zot", "region": "us-east-2", @@ -404,7 +403,7 @@ func TestCreateMetaDBDriver(t *testing.T) { "skipverify": false, } - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "dummy", } @@ -412,7 +411,7 @@ func TestCreateMetaDBDriver(t *testing.T) { So(err, ShouldNotBeNil) So(metaDB, ShouldBeNil) - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "redis", } @@ -420,7 +419,7 @@ func TestCreateMetaDBDriver(t *testing.T) { So(err, ShouldNotBeNil) So(metaDB, ShouldBeNil) - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "redis", "url": "url", } @@ -429,7 +428,7 @@ func TestCreateMetaDBDriver(t *testing.T) { So(err, ShouldNotBeNil) So(metaDB, ShouldBeNil) - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "redis", "url": "redis://" + miniRedis.Addr(), } @@ -559,7 +558,7 @@ func TestObjectStorageController(t *testing.T) { conf.HTTP.Port = port tmp := t.TempDir() - storageDriverParams := map[string]interface{}{ + storageDriverParams := map[string]any{ "rootdirectory": tmp, "name": storageConstants.S3StorageDriverName, } @@ -579,7 +578,7 @@ func TestObjectStorageController(t *testing.T) { endpoint := os.Getenv("S3MOCK_ENDPOINT") tmp := t.TempDir() - storageDriverParams := map[string]interface{}{ + storageDriverParams := map[string]any{ "rootdirectory": tmp, "name": storageConstants.S3StorageDriverName, "region": "us-east-2", @@ -606,7 +605,7 @@ func TestObjectStorageController(t *testing.T) { endpoint := os.Getenv("S3MOCK_ENDPOINT") - storageDriverParams := map[string]interface{}{ + storageDriverParams := map[string]any{ "rootdirectory": "/zot", "name": storageConstants.S3StorageDriverName, "region": "us-east-2", @@ -618,7 +617,7 @@ func TestObjectStorageController(t *testing.T) { conf.Storage.RemoteCache = true conf.Storage.StorageDriver = storageDriverParams - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "dynamodb", "endpoint": os.Getenv("DYNAMODBMOCK_ENDPOINT"), "region": "us-east-2", @@ -688,7 +687,7 @@ func TestObjectStorageControllerSubPaths(t *testing.T) { endpoint := os.Getenv("S3MOCK_ENDPOINT") tmp := t.TempDir() - storageDriverParams := map[string]interface{}{ + storageDriverParams := map[string]any{ "rootdirectory": tmp, "name": storageConstants.S3StorageDriverName, "region": "us-east-2", @@ -1286,7 +1285,7 @@ func TestScaleOutRequestProxy(t *testing.T) { clusterMembers := make([]string, numMembers) - for idx := 0; idx < numMembers; idx++ { + for idx := range numMembers { port := test.GetFreePort() ports[idx] = port clusterMembers[idx] = "127.0.0.1:" + port @@ -1357,7 +1356,7 @@ func TestScaleOutRequestProxy(t *testing.T) { clusterMembers := make([]string, numMembers) - for idx := 0; idx < numMembers; idx++ { + for idx := range numMembers { port := test.GetFreePort() ports[idx] = port clusterMembers[idx] = "127.0.0.1:" + port @@ -1457,7 +1456,7 @@ func TestScaleOutRequestProxy(t *testing.T) { clusterMembers := make([]string, numMembers) - for idx := 0; idx < numMembers; idx++ { + for idx := range numMembers { port := test.GetFreePort() ports[idx] = port clusterMembers[idx] = "127.0.0.1:" + port @@ -1521,7 +1520,7 @@ func TestScaleOutRequestProxy(t *testing.T) { clusterMembers := make([]string, numMembers) - for idx := 0; idx < numMembers; idx++ { + for idx := range numMembers { port := test.GetFreePort() ports[idx] = port clusterMembers[idx] = "127.0.0.1:" + port @@ -1587,7 +1586,7 @@ func TestScaleOutRequestProxy(t *testing.T) { clusterMembers := make([]string, numMembers) - for idx := 0; idx < numMembers; idx++ { + for idx := range numMembers { port := test.GetFreePort() ports[idx] = port clusterMembers[idx] = "127.0.0.1:" + port @@ -1724,7 +1723,7 @@ func TestInterruptedBlobUpload(t *testing.T) { // patch blob go func(ctx context.Context) { - for i := 0; i < 3; i++ { + for range 3 { _, _ = client.R(). SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). @@ -1780,7 +1779,7 @@ func TestInterruptedBlobUpload(t *testing.T) { // patch blob go func(ctx context.Context) { - for i := 0; i < 3; i++ { + for range 3 { _, _ = client.R(). SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). @@ -1839,7 +1838,7 @@ func TestInterruptedBlobUpload(t *testing.T) { // put blob go func(ctx context.Context) { - for i := 0; i < 3; i++ { + for range 3 { _, _ = client.R(). SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). @@ -1895,7 +1894,7 @@ func TestInterruptedBlobUpload(t *testing.T) { // push blob go func(ctx context.Context) { - for i := 0; i < 3; i++ { + for range 3 { _, _ = client.R(). SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). @@ -2672,6 +2671,7 @@ func TestTSLFailedReadingOfCACert(t *testing.T) { So(err, ShouldBeNil) errChan := make(chan error, 1) + go func() { err = ctlr.Run() errChan <- err @@ -2714,6 +2714,7 @@ func TestTSLFailedReadingOfCACert(t *testing.T) { So(err, ShouldBeNil) errChan := make(chan error, 1) + go func() { err = ctlr.Run() errChan <- err @@ -3028,7 +3029,7 @@ func newTestLDAPServer() *testLDAPServer { } func (l *testLDAPServer) Start(port int) { - addr := fmt.Sprintf("%s:%d", LDAPAddress, port) + addr := net.JoinHostPort(LDAPAddress, strconv.Itoa(port)) go func() { if err := l.server.ListenAndServe(addr); err != nil { @@ -3037,7 +3038,7 @@ func (l *testLDAPServer) Start(port int) { }() for { - _, err := net.Dial("tcp", addr) + _, err := net.Dial("tcp", addr) //nolint: noctx if err == nil { break } @@ -3250,7 +3251,7 @@ func TestBasicAuthWithReloadedCredentials(t *testing.T) { err = os.WriteFile(ldapConfigPath, []byte(newLdapConfigContent), 0o600) So(err, ShouldBeNil) - for i := 0; i < 10; i++ { + for range 10 { // test if the credentials don't work resp, _ = resty.R().SetBasicAuth(username, password).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) @@ -3267,7 +3268,7 @@ func TestBasicAuthWithReloadedCredentials(t *testing.T) { err = os.WriteFile(ldapConfigPath, []byte(ldapConfigContent), 0o600) So(err, ShouldBeNil) - for i := 0; i < 10; i++ { + for range 10 { // test if the credentials don't work resp, _ = resty.R().SetBasicAuth(username, password).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) @@ -3294,7 +3295,7 @@ func TestBasicAuthWithReloadedCredentials(t *testing.T) { err = os.WriteFile(configPath, []byte(configStr), 0o600) So(err, ShouldBeNil) - for i := 0; i < 10; i++ { + for range 10 { // test if the credentials don't work resp, _ = resty.R().SetBasicAuth(username, password).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) @@ -3311,7 +3312,7 @@ func TestBasicAuthWithReloadedCredentials(t *testing.T) { err = os.WriteFile(changedLdapConfigPath, []byte(ldapConfigContent), 0o600) So(err, ShouldBeNil) - for i := 0; i < 10; i++ { + for range 10 { // test if the credentials don't work resp, _ = resty.R().SetBasicAuth(username, password).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) @@ -3340,7 +3341,7 @@ func TestBasicAuthWithReloadedCredentials(t *testing.T) { // Loading the config should fail because the file doesn't exist so the old credentials // are still up and working fine. - for i := 0; i < 10; i++ { + for range 10 { // test if the credentials don't work resp, _ = resty.R().SetBasicAuth(username, password).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) @@ -7458,7 +7459,6 @@ func TestParallelRequests(t *testing.T) { // without creds, should get access error for i, testcase := range testCases { - testcase := testcase run := i t.Run(testcase.testCaseName, func(t *testing.T) { @@ -12187,7 +12187,7 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) { index.MediaType = ispec.MediaTypeImageIndex // upload multiple manifests - for i := 0; i < 4; i++ { + for i := range 4 { img := CreateImageWith().RandomLayers(1, 1000+i).DefaultConfig().Build() manifestDigest := img.ManifestDescriptor.Digest diff --git a/pkg/api/cookiestore.go b/pkg/api/cookiestore.go index 4b312af4..4107dad1 100644 --- a/pkg/api/cookiestore.go +++ b/pkg/api/cookiestore.go @@ -26,9 +26,10 @@ import ( const cookiesMaxAge = 7200 // 2h type CookieStore struct { + sessions.Store + needsCleanup bool // if store should be periodically cleaned rootDir string - sessions.Store } func (c *CookieStore) RunSessionCleaner(sch *scheduler.Scheduler) { @@ -48,7 +49,7 @@ func NewCookieStore( ) (*CookieStore, error) { // To store custom types in our cookies // we must first register them using gob.Register - gob.Register(map[string]interface{}{}) + gob.Register(map[string]any{}) var store sessions.Store diff --git a/pkg/api/errors/errors.go b/pkg/api/errors/errors.go index bf80eb11..60219bdc 100644 --- a/pkg/api/errors/errors.go +++ b/pkg/api/errors/errors.go @@ -1,6 +1,8 @@ package errors import ( + "maps" + "zotregistry.dev/zot/v2/errors" ) @@ -156,9 +158,7 @@ func NewError(code ErrorCode) *Error { } func (err *Error) AddDetail(m map[string]string) *Error { - for k, v := range m { - err.Detail[k] = v - } + maps.Copy(err.Detail, m) return err } diff --git a/pkg/api/htpasswd_test.go b/pkg/api/htpasswd_test.go index a235da4b..d7260c6c 100644 --- a/pkg/api/htpasswd_test.go +++ b/pkg/api/htpasswd_test.go @@ -2,6 +2,7 @@ package api_test import ( "os" + "strings" "testing" "time" @@ -274,11 +275,14 @@ func TestHTPasswdWatcher(t *testing.T) { So(test.WaitForLogMessages(logBuffer, "htpasswd watcher terminating...", 1, 5*time.Second), ShouldBeTrue) // Test with very long file path - longPath := "/tmp/" - for i := 0; i < 100; i++ { - longPath += "verylongdirname" + var longPathBuilder strings.Builder + longPathBuilder.WriteString("/tmp/") + + for range 100 { + longPathBuilder.WriteString("verylongdirname") } - longPath += "/htpasswd" + longPathBuilder.WriteString("/htpasswd") + longPath := longPathBuilder.String() htw3, err := api.NewHTPasswdWatcher(htp, longPath) So(err, ShouldBeNil) So(func() { htw3.Run() }, ShouldNotPanic) @@ -315,14 +319,14 @@ func TestHTPasswdWatcher(t *testing.T) { // Test concurrent Run() and Close() go func() { - for i := 0; i < 5; i++ { + for range 5 { htw.Run() time.Sleep(1 * time.Millisecond) } }() go func() { - for i := 0; i < 5; i++ { + for range 5 { htw.Close() time.Sleep(1 * time.Millisecond) } @@ -337,7 +341,7 @@ func TestHTPasswdWatcher(t *testing.T) { defer htw.Close() go func() { - for i := 0; i < 3; i++ { + for range 3 { _ = htw.ChangeFile(htpasswdPath1) time.Sleep(1 * time.Millisecond) @@ -345,7 +349,7 @@ func TestHTPasswdWatcher(t *testing.T) { }() go func() { - for i := 0; i < 3; i++ { + for range 3 { _ = htw.ChangeFile(htpasswdPath2) time.Sleep(1 * time.Millisecond) @@ -383,7 +387,7 @@ func TestHTPasswdWatcher(t *testing.T) { So(test.WaitForLogMessages(logBuffer, "htpasswd watcher terminating...", 1, 5*time.Second), ShouldBeTrue) // Test multiple Run/Close cycles - for i := 0; i < 3; i++ { + for range 3 { htw2.Run() time.Sleep(10 * time.Millisecond) So(htw2.Close(), ShouldBeNil) @@ -432,7 +436,7 @@ func TestHTPasswdWatcher(t *testing.T) { So(test.WaitForLogMessages(logBuffer, "htpasswd watcher terminating...", 2, 5*time.Second), ShouldBeTrue) // Test 3: Multiple termination cycles with file watching - for i := 0; i < 3; i++ { + for range 3 { htw2.Run() time.Sleep(10 * time.Millisecond) So(htw2.Close(), ShouldBeNil) @@ -443,7 +447,7 @@ func TestHTPasswdWatcher(t *testing.T) { So(test.WaitForLogMessages(logBuffer, "htpasswd watcher terminating...", 3, 5*time.Second), ShouldBeTrue) // Test 4: Stress test with rapid cycles - for i := 0; i < 5; i++ { + for range 5 { htw2.Run() time.Sleep(5 * time.Millisecond) So(htw2.Close(), ShouldBeNil) diff --git a/pkg/api/ldap.go b/pkg/api/ldap.go index 18438fc5..1b089e41 100644 --- a/pkg/api/ldap.go +++ b/pkg/api/ldap.go @@ -1,5 +1,3 @@ -// Package ldap provides a simple ldap client to authenticate, -// retrieve basic information and groups for a user. package api import ( diff --git a/pkg/api/proxy.go b/pkg/api/proxy.go index 5d2ff7e6..3ede34ac 100644 --- a/pkg/api/proxy.go +++ b/pkg/api/proxy.go @@ -215,11 +215,11 @@ func copyHeader(dst, src http.Header) { } } -// identifies and returns the cluster socket and index. -// this is the socket which the scale out cluster members will use for +// GetLocalMemberClusterSocket identifies and returns the cluster socket and index. +// This is the socket which the scale out cluster members will use for // proxying and communication among each other. -// returns index, socket, error. -// returns an empty string and index value -1 if the cluster socket is not found. +// Returns index, socket, error. +// Returns an empty string and index value -1 if the cluster socket is not found. func GetLocalMemberClusterSocket(members []string, localSockets []string) (int, string, error) { for memberIdx, member := range members { // for each member, get the full list of sockets, including DNS resolution diff --git a/pkg/api/proxy_test.go b/pkg/api/proxy_test.go index c0a75743..8617bba9 100644 --- a/pkg/api/proxy_test.go +++ b/pkg/api/proxy_test.go @@ -1,5 +1,4 @@ //go:build sync && scrub && metrics && search && lint && userprefs && mgmt && imagetrust && ui -// +build sync,scrub,metrics,search,lint,userprefs,mgmt,imagetrust,ui package api_test diff --git a/pkg/api/routes.go b/pkg/api/routes.go index 9da4f246..d3b8872a 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -1722,6 +1722,7 @@ finish: rh.c.Log.Error().Err(err).Str("blobUpload", sessionID).Str("repository", name). Msg("failed to remove blobUpload in repo") } + response.WriteHeader(http.StatusInternalServerError) } @@ -1963,7 +1964,7 @@ func (rh *RouteHandler) Logout(response http.ResponseWriter, request *http.Reque response.WriteHeader(http.StatusOK) } -// github Oauth2 CodeExchange callback. +// GithubCodeExchangeCallback is a github Oauth2 CodeExchange callback. func (rh *RouteHandler) GithubCodeExchangeCallback() rp.CodeExchangeCallback[*oidc.IDTokenClaims] { return func(w http.ResponseWriter, r *http.Request, tokens *oidc.Tokens[*oidc.IDTokenClaims], state string, relyingParty rp.RelyingParty, @@ -1998,7 +1999,7 @@ func (rh *RouteHandler) GithubCodeExchangeCallback() rp.CodeExchangeCallback[*oi } } -// Openid CodeExchange callback (legacy, kept for compatibility). +// OpenIDCodeExchangeCallback is an Openid CodeExchange callback (legacy, kept for compatibility). func (rh *RouteHandler) OpenIDCodeExchangeCallback() rp.CodeExchangeUserinfoCallback[ *oidc.IDTokenClaims, *oidc.UserInfo, @@ -2072,7 +2073,7 @@ func (rh *RouteHandler) OpenIDCodeExchangeCallbackWithProvider(providerName stri var groups []string - val, ok := info.Claims["groups"].([]interface{}) + val, ok := info.Claims["groups"].([]any) if !ok { rh.c.Log.Info().Msgf("failed to find any 'groups' claim for user %s in UserInfo", username) } @@ -2081,7 +2082,7 @@ func (rh *RouteHandler) OpenIDCodeExchangeCallbackWithProvider(providerName stri groups = append(groups, fmt.Sprint(group)) } - val, ok = tokens.IDTokenClaims.Claims["groups"].([]interface{}) + val, ok = tokens.IDTokenClaims.Claims["groups"].([]any) if !ok { rh.c.Log.Info().Msgf("failed to find any 'groups' claim for user %s in IDTokenClaimsToken", username) } @@ -2316,6 +2317,7 @@ func (rh *RouteHandler) CreateAPIKey(resp http.ResponseWriter, req *http.Request apiKeyResponse := struct { mTypes.APIKeyDetails + APIKey string `json:"apiKey"` }{ APIKey: fmt.Sprintf("%s%s", constants.APIKeysPrefix, apiKey), diff --git a/pkg/api/routes_test.go b/pkg/api/routes_test.go index 5f59479d..415141ec 100644 --- a/pkg/api/routes_test.go +++ b/pkg/api/routes_test.go @@ -1,5 +1,4 @@ //go:build sync && scrub && metrics && search && lint && mgmt -// +build sync,scrub,metrics,search,lint,mgmt package api_test @@ -127,7 +126,7 @@ func TestRoutes(t *testing.T) { tokens := &oidc.Tokens[*oidc.IDTokenClaims]{ IDTokenClaims: &oidc.IDTokenClaims{ Claims: map[string]any{ - "groups": []interface{}{"group1", "group3"}, + "groups": []any{"group1", "group3"}, }, }, } @@ -138,7 +137,7 @@ func TestRoutes(t *testing.T) { Subject: "sub", Claims: map[string]any{ "email": "test@test.com", - "groups": []interface{}{"group1", "group2"}, + "groups": []any{"group1", "group2"}, }, UserInfoEmail: oidc.UserInfoEmail{Email: "test@test.com"}, } diff --git a/pkg/api/runtime.go b/pkg/api/runtime.go index 92577e34..79f28764 100644 --- a/pkg/api/runtime.go +++ b/pkg/api/runtime.go @@ -1,5 +1,4 @@ //go:build !windows -// +build !windows package api diff --git a/pkg/api/runtime_windows.go b/pkg/api/runtime_windows.go index 51325cc0..3d1b7400 100644 --- a/pkg/api/runtime_windows.go +++ b/pkg/api/runtime_windows.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package api diff --git a/pkg/api/session.go b/pkg/api/session.go index b99ae39c..45f5c346 100644 --- a/pkg/api/session.go +++ b/pkg/api/session.go @@ -16,6 +16,7 @@ import ( type statusWriter struct { http.ResponseWriter + status int length int } diff --git a/pkg/cli/client/cli.go b/pkg/cli/client/cli.go index aee53339..48e7232c 100644 --- a/pkg/cli/client/cli.go +++ b/pkg/cli/client/cli.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/client.go b/pkg/cli/client/client.go index c492ed20..2163dbdb 100644 --- a/pkg/cli/client/client.go +++ b/pkg/cli/client/client.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client @@ -28,7 +27,7 @@ var ( ) func makeGETRequest(ctx context.Context, url, username, password string, - verifyTLS bool, debug bool, resultsPtr interface{}, configWriter io.Writer, + verifyTLS bool, debug bool, resultsPtr any, configWriter io.Writer, ) (http.Header, error) { req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { @@ -54,7 +53,7 @@ func makeHEADRequest(ctx context.Context, url, username, password string, verify } func makeGraphQLRequest(ctx context.Context, url, query, username, - password string, verifyTLS bool, debug bool, resultsPtr interface{}, configWriter io.Writer, + password string, verifyTLS bool, debug bool, resultsPtr any, configWriter io.Writer, ) error { req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, bytes.NewBufferString(query)) if err != nil { @@ -78,7 +77,7 @@ func makeGraphQLRequest(ctx context.Context, url, query, username, } func doHTTPRequest(req *http.Request, verifyTLS bool, debug bool, - resultsPtr interface{}, configWriter io.Writer, + resultsPtr any, configWriter io.Writer, ) (http.Header, error) { var httpClient *http.Client @@ -518,14 +517,13 @@ func isNotationSigned(ctx context.Context, repo, digestStr string, searchConf Se func isCosignSigned(ctx context.Context, repo, digestStr string, searchConf SearchConfig, username, password string, ) bool { - var result interface{} + var result any cosignTag := strings.Replace(digestStr, ":", "-", 1) + "." + common.CosignSignatureTagSuffix URL := fmt.Sprintf("%s/v2/%s/manifests/%s", searchConf.ServURL, repo, cosignTag) _, err := makeGETRequest(ctx, URL, username, password, searchConf.VerifyTLS, searchConf.Debug, &result, searchConf.ResultWriter) - if err == nil { return true } diff --git a/pkg/cli/client/client_test.go b/pkg/cli/client/client_test.go index 285d5360..a45cc39d 100644 --- a/pkg/cli/client/client_test.go +++ b/pkg/cli/client/client_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client_test diff --git a/pkg/cli/client/config_cmd.go b/pkg/cli/client/config_cmd.go index 91e503d2..34a8e779 100644 --- a/pkg/cli/client/config_cmd.go +++ b/pkg/cli/client/config_cmd.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client @@ -8,6 +7,7 @@ import ( "fmt" "os" "path" + "slices" "strconv" "strings" "text/tabwriter" @@ -41,6 +41,7 @@ func NewConfigCommand() *cobra.Command { } configPath := path.Join(home, "/.zot") + switch len(args) { case noArgs: if isListing { // zot config -l @@ -162,7 +163,7 @@ func NewConfigRemoveCommand() *cobra.Command { return configRemoveCmd } -func getConfigMapFromFile(filePath string) ([]interface{}, error) { +func getConfigMapFromFile(filePath string) ([]any, error) { file, err := os.OpenFile(filePath, os.O_RDONLY|os.O_CREATE, defaultConfigPerms) if err != nil { return nil, err @@ -175,7 +176,7 @@ func getConfigMapFromFile(filePath string) ([]interface{}, error) { return nil, err } - var jsonMap map[string]interface{} + var jsonMap map[string]any json := jsoniter.ConfigCompatibleWithStandardLibrary @@ -185,7 +186,7 @@ func getConfigMapFromFile(filePath string) ([]interface{}, error) { return nil, zerr.ErrEmptyJSON } - configs, ok := jsonMap["configs"].([]interface{}) + configs, ok := jsonMap["configs"].([]any) if !ok { return nil, zerr.ErrCliBadConfig } @@ -193,10 +194,10 @@ func getConfigMapFromFile(filePath string) ([]interface{}, error) { return configs, nil } -func saveConfigMapToFile(filePath string, configMap []interface{}) error { +func saveConfigMapToFile(filePath string, configMap []any) error { json := jsoniter.ConfigCompatibleWithStandardLibrary - listMap := make(map[string]interface{}) + listMap := make(map[string]any) listMap["configs"] = configMap marshalled, err := json.MarshalIndent(&listMap, "", " ") @@ -226,7 +227,7 @@ func getConfigNames(configPath string) (string, error) { writer := tabwriter.NewWriter(&builder, 0, 8, 1, '\t', tabwriter.AlignRight) //nolint:mnd for _, val := range configs { - configMap, ok := val.(map[string]interface{}) + configMap, ok := val.(map[string]any) if !ok { return "", zerr.ErrBadConfig } @@ -256,7 +257,7 @@ func addConfig(configPath, configName, url string) error { return zerr.ErrDuplicateConfigName } - configMap := make(map[string]interface{}) + configMap := make(map[string]any) configMap["url"] = url configMap[nameKey] = configName addDefaultConfigs(configMap) @@ -277,7 +278,7 @@ func removeConfig(configPath, configName string) error { } for i, val := range configs { - configMap, ok := val.(map[string]interface{}) + configMap, ok := val.(map[string]any) if !ok { return zerr.ErrBadConfig } @@ -302,7 +303,7 @@ func removeConfig(configPath, configName string) error { return zerr.ErrConfigNotFound } -func addDefaultConfigs(config map[string]interface{}) { +func addDefaultConfigs(config map[string]any) { if _, ok := config[showspinnerConfig]; !ok { config[showspinnerConfig] = true } @@ -323,7 +324,7 @@ func getConfigValue(configPath, configName, key string) (string, error) { } for _, val := range configs { - configMap, ok := val.(map[string]interface{}) + configMap, ok := val.(map[string]any) if !ok { return "", zerr.ErrBadConfig } @@ -358,7 +359,7 @@ func resetConfigValue(configPath, configName, key string) error { } for _, val := range configs { - configMap, ok := val.(map[string]interface{}) + configMap, ok := val.(map[string]any) if !ok { return zerr.ErrBadConfig } @@ -396,7 +397,7 @@ func setConfigValue(configPath, configName, key, value string) error { } for _, val := range configs { - configMap, ok := val.(map[string]interface{}) + configMap, ok := val.(map[string]any) if !ok { return zerr.ErrBadConfig } @@ -437,7 +438,7 @@ func getAllConfig(configPath, configName string) (string, error) { var builder strings.Builder for _, value := range configs { - configMap, ok := value.(map[string]interface{}) + configMap, ok := value.(map[string]any) if !ok { return "", zerr.ErrBadConfig } @@ -461,19 +462,15 @@ func getAllConfig(configPath, configName string) (string, error) { return "", zerr.ErrConfigNotFound } -func configNameExists(configs []interface{}, configName string) bool { - for _, val := range configs { - configMap, ok := val.(map[string]interface{}) +func configNameExists(configs []any, configName string) bool { + return slices.ContainsFunc(configs, func(val any) bool { + configMap, ok := val.(map[string]any) if !ok { return false } - if configMap[nameKey] == configName { - return true - } - } - - return false + return configMap[nameKey] == configName + }) } const ( diff --git a/pkg/cli/client/config_cmd_test.go b/pkg/cli/client/config_cmd_test.go index 371c2ea4..acc3e4f9 100644 --- a/pkg/cli/client/config_cmd_test.go +++ b/pkg/cli/client/config_cmd_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client_test diff --git a/pkg/cli/client/cve_cmd_internal_test.go b/pkg/cli/client/cve_cmd_internal_test.go index 238f5b5b..5c0f0a80 100644 --- a/pkg/cli/client/cve_cmd_internal_test.go +++ b/pkg/cli/client/cve_cmd_internal_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/cve_cmd_test.go b/pkg/cli/client/cve_cmd_test.go index 8abc53ad..5c31c6cf 100644 --- a/pkg/cli/client/cve_cmd_test.go +++ b/pkg/cli/client/cve_cmd_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client_test @@ -1131,10 +1130,8 @@ func getMockCveScanner(metaDB mTypes.MetaDB) cveinfo.Scanner { for _, imageLayer := range manifestData.Manifests[0].Manifest.Layers { switch imageLayer.MediaType { case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer): - return true, nil default: - return false, zerr.ErrScanNotSupported } } diff --git a/pkg/cli/client/cves_cmd.go b/pkg/cli/client/cves_cmd.go index 4892e002..2fe0215d 100644 --- a/pkg/cli/client/cves_cmd.go +++ b/pkg/cli/client/cves_cmd.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/cves_sub_cmd.go b/pkg/cli/client/cves_sub_cmd.go index 7577776d..c9fa3699 100644 --- a/pkg/cli/client/cves_sub_cmd.go +++ b/pkg/cli/client/cves_sub_cmd.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/discover.go b/pkg/cli/client/discover.go index 08ed4398..072ad92b 100644 --- a/pkg/cli/client/discover.go +++ b/pkg/cli/client/discover.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/elevated_test.go b/pkg/cli/client/elevated_test.go index be4fe442..fd2955f1 100644 --- a/pkg/cli/client/elevated_test.go +++ b/pkg/cli/client/elevated_test.go @@ -1,5 +1,4 @@ //go:build search && needprivileges -// +build search,needprivileges package client_test @@ -25,6 +24,7 @@ import ( func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { Convey("Privileged certs - Make a new controller", t, func() { + //nolint: noctx // old code, no context available cmd := exec.Command("mkdir", "-p", "/etc/containers/certs.d/127.0.0.1:8089/") //nolint: gosec _, err := cmd.Output() @@ -32,6 +32,7 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { panic(err) } + //nolint: noctx // old code, no context available defer exec.Command("rm", "-rf", "/etc/containers/certs.d/127.0.0.1:8089/") workDir, _ := os.Getwd() @@ -41,6 +42,7 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { caGlob, _ := filepath.Glob("ca.*") for _, file := range clientGlob { + //nolint: noctx // old code, no context available cmd = exec.Command("cp", file, "/etc/containers/certs.d/127.0.0.1:8089/") res, err := cmd.CombinedOutput() @@ -50,6 +52,7 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { } for _, file := range caGlob { + //nolint: noctx // old code, no context available cmd = exec.Command("cp", file, "/etc/containers/certs.d/127.0.0.1:8089/") res, err := cmd.CombinedOutput() @@ -61,6 +64,7 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { allGlob, _ := filepath.Glob("/etc/containers/certs.d/127.0.0.1:8089/*.key") for _, file := range allGlob { + //nolint: noctx // old code, no context available cmd = exec.Command("chmod", "a=rwx", file) res, err := cmd.CombinedOutput() diff --git a/pkg/cli/client/flags.go b/pkg/cli/client/flags.go index fd204d43..e6094a1a 100644 --- a/pkg/cli/client/flags.go +++ b/pkg/cli/client/flags.go @@ -1,14 +1,13 @@ //go:build search -// +build search package client import ( "fmt" + "slices" "strings" zerr "zotregistry.dev/zot/v2/errors" - "zotregistry.dev/zot/v2/pkg/common" ) const ( @@ -91,7 +90,7 @@ func (e *CVEListSortFlag) String() string { } func (e *CVEListSortFlag) Set(val string) error { - if !common.Contains(CVEListSortOptions(), val) { + if !slices.Contains(CVEListSortOptions(), val) { return fmt.Errorf("%w %s", zerr.ErrFlagValueUnsupported, CVEListSortOptionsStr()) } @@ -111,7 +110,7 @@ func (e *ImageListSortFlag) String() string { } func (e *ImageListSortFlag) Set(val string) error { - if !common.Contains(ImageListSortOptions(), val) { + if !slices.Contains(ImageListSortOptions(), val) { return fmt.Errorf("%w %s", zerr.ErrFlagValueUnsupported, ImageListSortOptionsStr()) } @@ -131,7 +130,7 @@ func (e *ImageSearchSortFlag) String() string { } func (e *ImageSearchSortFlag) Set(val string) error { - if !common.Contains(ImageSearchSortOptions(), val) { + if !slices.Contains(ImageSearchSortOptions(), val) { return fmt.Errorf("%w %s", zerr.ErrFlagValueUnsupported, ImageSearchSortOptionsStr()) } @@ -151,7 +150,7 @@ func (e *RepoListSortFlag) String() string { } func (e *RepoListSortFlag) Set(val string) error { - if !common.Contains(RepoListSortOptions(), val) { + if !slices.Contains(RepoListSortOptions(), val) { return fmt.Errorf("%w %s", zerr.ErrFlagValueUnsupported, RepoListSortOptionsStr()) } diff --git a/pkg/cli/client/flags_test.go b/pkg/cli/client/flags_test.go index 356d5ec7..a83f357d 100644 --- a/pkg/cli/client/flags_test.go +++ b/pkg/cli/client/flags_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client_test diff --git a/pkg/cli/client/gql_queries.go b/pkg/cli/client/gql_queries.go index 3f90d01a..5a01f1b5 100644 --- a/pkg/cli/client/gql_queries.go +++ b/pkg/cli/client/gql_queries.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/gql_queries_test.go b/pkg/cli/client/gql_queries_test.go index c727665f..4f89c25f 100644 --- a/pkg/cli/client/gql_queries_test.go +++ b/pkg/cli/client/gql_queries_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client_test diff --git a/pkg/cli/client/image_cmd.go b/pkg/cli/client/image_cmd.go index 70dc8336..a07fd4dd 100644 --- a/pkg/cli/client/image_cmd.go +++ b/pkg/cli/client/image_cmd.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/image_cmd_internal_test.go b/pkg/cli/client/image_cmd_internal_test.go index 90c20a91..f2ebcc3e 100644 --- a/pkg/cli/client/image_cmd_internal_test.go +++ b/pkg/cli/client/image_cmd_internal_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/image_cmd_test.go b/pkg/cli/client/image_cmd_test.go index 3464738b..ed69aeb5 100644 --- a/pkg/cli/client/image_cmd_test.go +++ b/pkg/cli/client/image_cmd_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client_test diff --git a/pkg/cli/client/image_sub_cmd.go b/pkg/cli/client/image_sub_cmd.go index 88fb5950..250b3023 100644 --- a/pkg/cli/client/image_sub_cmd.go +++ b/pkg/cli/client/image_sub_cmd.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/repo_cmd.go b/pkg/cli/client/repo_cmd.go index 727ded02..51394d73 100644 --- a/pkg/cli/client/repo_cmd.go +++ b/pkg/cli/client/repo_cmd.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/repo_sub_cmd.go b/pkg/cli/client/repo_sub_cmd.go index 1a548240..7be2c467 100644 --- a/pkg/cli/client/repo_sub_cmd.go +++ b/pkg/cli/client/repo_sub_cmd.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/repo_test.go b/pkg/cli/client/repo_test.go index 568c1a7e..fa41d925 100644 --- a/pkg/cli/client/repo_test.go +++ b/pkg/cli/client/repo_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client_test diff --git a/pkg/cli/client/root.go b/pkg/cli/client/root.go index d70792cb..b42f860d 100644 --- a/pkg/cli/client/root.go +++ b/pkg/cli/client/root.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client @@ -11,7 +10,7 @@ import ( "zotregistry.dev/zot/v2/pkg/log" ) -// "zli" - client-side cli. +// NewCliRootCmd creates the root command for "zli" - client-side cli. func NewCliRootCmd() *cobra.Command { showVersion := false diff --git a/pkg/cli/client/root_test.go b/pkg/cli/client/root_test.go index aee303cc..ea93487f 100644 --- a/pkg/cli/client/root_test.go +++ b/pkg/cli/client/root_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client_test diff --git a/pkg/cli/client/search_cmd.go b/pkg/cli/client/search_cmd.go index 0bcf4c8b..3ba0919e 100644 --- a/pkg/cli/client/search_cmd.go +++ b/pkg/cli/client/search_cmd.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/search_cmd_internal_test.go b/pkg/cli/client/search_cmd_internal_test.go index 69502ea5..06644881 100644 --- a/pkg/cli/client/search_cmd_internal_test.go +++ b/pkg/cli/client/search_cmd_internal_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/search_cmd_test.go b/pkg/cli/client/search_cmd_test.go index a322cb9a..640fef70 100644 --- a/pkg/cli/client/search_cmd_test.go +++ b/pkg/cli/client/search_cmd_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client_test diff --git a/pkg/cli/client/search_functions.go b/pkg/cli/client/search_functions.go index e9f116ab..6e36fcdc 100644 --- a/pkg/cli/client/search_functions.go +++ b/pkg/cli/client/search_functions.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/search_functions_internal_test.go b/pkg/cli/client/search_functions_internal_test.go index 196a7b1b..f27c3242 100644 --- a/pkg/cli/client/search_functions_internal_test.go +++ b/pkg/cli/client/search_functions_internal_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search // //nolint:dupl diff --git a/pkg/cli/client/search_sub_cmd.go b/pkg/cli/client/search_sub_cmd.go index dc31c6da..280fbe09 100644 --- a/pkg/cli/client/search_sub_cmd.go +++ b/pkg/cli/client/search_sub_cmd.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/server_info_cmd.go b/pkg/cli/client/server_info_cmd.go index d9967332..041c0af6 100644 --- a/pkg/cli/client/server_info_cmd.go +++ b/pkg/cli/client/server_info_cmd.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/client/server_info_cmd_test.go b/pkg/cli/client/server_info_cmd_test.go index 3307082b..543c6b65 100644 --- a/pkg/cli/client/server_info_cmd_test.go +++ b/pkg/cli/client/server_info_cmd_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client //nolint:testpackage diff --git a/pkg/cli/client/service.go b/pkg/cli/client/service.go index 43b21c7f..c8794b10 100644 --- a/pkg/cli/client/service.go +++ b/pkg/cli/client/service.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client @@ -687,7 +686,7 @@ func (service searchService) getImagesByDigest(ctx context.Context, config Searc // errors are returned in the stringResult channel, the unmarshalled payload is in resultPtr. func (service searchService) makeGraphQLQuery(ctx context.Context, config SearchConfig, username, password, query string, - resultPtr interface{}, + resultPtr any, ) error { endPoint, err := combineServerAndEndpointURL(config.ServURL, constants.FullSearchPrefix) if err != nil { diff --git a/pkg/cli/client/utils.go b/pkg/cli/client/utils.go index 394f05c3..cdd6a346 100644 --- a/pkg/cli/client/utils.go +++ b/pkg/cli/client/utils.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client @@ -251,9 +250,9 @@ func printReferrersTableHeader(config SearchConfig, writer io.Writer, maxArtifac if maxArtifactTypeLen > len("ARTIFACT TYPE") { offset = strings.Repeat(" ", maxArtifactTypeLen-len("ARTIFACT TYPE")) - row[refArtifactTypeIndex] = "ARTIFACT TYPE" + offset + row[refArtifactTypeIndex] = "ARTIFACT TYPE" + offset //nolint: gosec } else { - row[refArtifactTypeIndex] = "ARTIFACT TYPE" + row[refArtifactTypeIndex] = "ARTIFACT TYPE" //nolint: gosec } row[refDigestIndex] = "DIGEST" @@ -290,9 +289,9 @@ func printRepoTableHeader(writer io.Writer, repoMaxLen, maxTimeLen int, verbose if repoMaxLen > len("LAST UPDATED") { offset = strings.Repeat(" ", repoMaxLen-len("LAST UPDATED")) - row[repoLastUpdatedIndex] = "LAST UPDATED" + offset + row[repoLastUpdatedIndex] = "LAST UPDATED" + offset //nolint: gosec } else { - row[repoLastUpdatedIndex] = "LAST UPDATED" + row[repoLastUpdatedIndex] = "LAST UPDATED" //nolint: gosec } row[repoSizeIndex] = sizeColumn diff --git a/pkg/cli/client/utils_internal_test.go b/pkg/cli/client/utils_internal_test.go index 61c5378f..e7aec78e 100644 --- a/pkg/cli/client/utils_internal_test.go +++ b/pkg/cli/client/utils_internal_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package client diff --git a/pkg/cli/server/config_reloader_test.go b/pkg/cli/server/config_reloader_test.go index 3c3711b3..3dad274b 100644 --- a/pkg/cli/server/config_reloader_test.go +++ b/pkg/cli/server/config_reloader_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package server_test diff --git a/pkg/cli/server/extensions_test.go b/pkg/cli/server/extensions_test.go index ecb0798d..0cb75bd1 100644 --- a/pkg/cli/server/extensions_test.go +++ b/pkg/cli/server/extensions_test.go @@ -1,5 +1,4 @@ //go:build sync && scrub && metrics && search && userprefs && mgmt && imagetrust && events -// +build sync,scrub,metrics,search,userprefs,mgmt,imagetrust,events package server_test diff --git a/pkg/cli/server/root.go b/pkg/cli/server/root.go index d3cd47ac..f8215858 100644 --- a/pkg/cli/server/root.go +++ b/pkg/cli/server/root.go @@ -10,6 +10,7 @@ import ( "path" "path/filepath" "regexp" + "slices" "strconv" "strings" "time" @@ -24,7 +25,6 @@ import ( "zotregistry.dev/zot/v2/pkg/api" "zotregistry.dev/zot/v2/pkg/api/config" "zotregistry.dev/zot/v2/pkg/api/constants" - "zotregistry.dev/zot/v2/pkg/common" extconf "zotregistry.dev/zot/v2/pkg/extensions/config" eventsconf "zotregistry.dev/zot/v2/pkg/extensions/config/events" "zotregistry.dev/zot/v2/pkg/extensions/monitoring" @@ -203,7 +203,7 @@ func newVerifyFeatureCmd(conf *config.Config) *cobra.Command { return verifyFeatureCmd } -// "zot" - registry server. +// NewServerRootCmd creates a "zot" registry server command. func NewServerRootCmd() *cobra.Command { showVersion := false conf := config.New() @@ -908,7 +908,7 @@ func LoadConfiguration(config *config.Config, configPath string) error { /* if file extension is not supported, try everything it's also possible that the filename is starting with a dot eg: ".config". */ - if !common.Contains(viper.SupportedExts, ext) { + if !slices.Contains(viper.SupportedExts, ext) { ext = "" } diff --git a/pkg/cli/server/root_test.go b/pkg/cli/server/root_test.go index 9b41106f..f1d9a57d 100644 --- a/pkg/cli/server/root_test.go +++ b/pkg/cli/server/root_test.go @@ -668,7 +668,7 @@ storage: }, { "Should fail verify if session driver is enabled and sessionKeysFile present", - []byte(fmt.Sprintf(`{ + fmt.Appendf([]byte{}, `{ "storage":{ "rootDirectory":"/tmp/zot" }, @@ -698,7 +698,7 @@ storage: "enable": true } } - }`, tmpSessionKeysFile.Name())), + }`, tmpSessionKeysFile.Name()), false, zerr.ErrBadConfig.Error() + ": session keys not supported when redis session driver is used!", }, @@ -1562,12 +1562,12 @@ storage: err = tmpCredsFile.Close() So(err, ShouldBeNil) - content = []byte(fmt.Sprintf(`{"distSpecVersion":"1.1.1","storage":{"rootDirectory":"/tmp/zot"}, + content = fmt.Appendf([]byte{}, `{"distSpecVersion":"1.1.1","storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"openid":{"providers":{"oidc":{"issuer":"http://127.0.0.1:5556/dex", "credentialsFile":"%s","scopes":["openid"]}}}}}, "log":{"level":"debug"}}`, - tmpCredsFile.Name()), + tmpCredsFile.Name(), ) _, err = tmpfile.Write(content) So(err, ShouldBeNil) @@ -1677,11 +1677,11 @@ storage: err = tmpCredsFile.Close() So(err, ShouldBeNil) - content = []byte(fmt.Sprintf(`{ "distSpecVersion": "1.1.1", + content = fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "/tmp/zot" }, "http": { "address": "127.0.0.1", "port": "8080", "auth":{"htpasswd":{"path":"test/data/htpasswd"}, "sessionKeysFile": "%s", "failDelay": 5 } }, "log": { "level": "debug" } }`, - tmpCredsFile.Name()), + tmpCredsFile.Name(), ) _, err = tmpFile.Write(content) @@ -1712,11 +1712,11 @@ storage: err = tmpCredsFile.Close() So(err, ShouldBeNil) - content = []byte(fmt.Sprintf(`{ "distSpecVersion": "1.1.1", + content = fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "/tmp/zot" }, "http": { "address": "127.0.0.1", "port": "8080", "auth":{"htpasswd":{"path":"test/data/htpasswd"}, "sessionKeysFile": "%s", "failDelay": 5 } }, "log": { "level": "debug" } }`, - tmpCredsFile.Name()), + tmpCredsFile.Name(), ) _, err = tmpFile.Write(content) @@ -1748,13 +1748,13 @@ storage: err = tmpCredsFile.Close() So(err, ShouldBeNil) - content = []byte(fmt.Sprintf(`{ "distSpecVersion": "1.1.1", + content = fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "/tmp/zot" }, "http": { "address": "127.0.0.1", "port": "8080", "auth": { "ldap": { "credentialsFile": "%v", "address": "ldap.example.org", "port": 389, "startTLS": false, "baseDN": "ou=Users,dc=example,dc=org", "userAttribute": "uid", "userGroupAttribute": "memberOf", "skipVerify": true, "subtreeSearch": true }, "failDelay": 5 } }, "log": { "level": "debug" } }`, - tmpCredsFile.Name()), + tmpCredsFile.Name(), ) _, err = tmpFile.Write(content) @@ -1786,13 +1786,13 @@ storage: err = tmpCredsFile.Close() So(err, ShouldBeNil) - content = []byte(fmt.Sprintf(`{ "distSpecVersion": "1.1.1", + content = fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "/tmp/zot" }, "http": { "address": "127.0.0.1", "port": "8080", "auth": { "ldap": { "credentialsFile": "%v", "address": "ldap.example.org", "port": 389, "startTLS": false, "baseDN": "ou=Users,dc=example,dc=org", "userAttribute": "uid", "userGroupAttribute": "memberOf", "skipVerify": true, "subtreeSearch": true }, "failDelay": 5 } }, "log": { "level": "debug" } }`, - tmpCredsFile.Name()), + tmpCredsFile.Name(), ) _, err = tmpFile.Write(content) @@ -1826,13 +1826,13 @@ storage: err = tmpCredsFile.Close() So(err, ShouldBeNil) - content = []byte(fmt.Sprintf(`{ "distSpecVersion": "1.1.1", + content = fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "/tmp/zot" }, "http": { "address": "127.0.0.1", "port": "8080", "auth": { "ldap": { "credentialsFile": "%v", "address": "ldap.example.org", "port": 389, "startTLS": false, "baseDN": "ou=Users,dc=example,dc=org", "userAttribute": "uid", "userGroupAttribute": "memberOf", "skipVerify": true, "subtreeSearch": true }, "failDelay": 5 } }, "log": { "level": "debug" } }`, - tmpCredsFile.Name()), + tmpCredsFile.Name(), ) _, err = tmpFile.Write(content) @@ -1863,13 +1863,13 @@ storage: err = tmpCredsFile.Close() So(err, ShouldBeNil) - content = []byte(fmt.Sprintf(`{ "distSpecVersion": "1.1.1", + content = fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "/tmp/zot" }, "http": { "address": "127.0.0.1", "port": "8080", "auth": { "ldap": { "credentialsFile": "%v", "address": "ldap.example.org", "port": 389, "startTLS": false, "baseDN": "ou=Users,dc=example,dc=org", "userAttribute": "uid", "userGroupAttribute": "memberOf", "skipVerify": true, "subtreeSearch": true }, "failDelay": 5 } }, "log": { "level": "debug" } }`, - tmpCredsFile.Name()), + tmpCredsFile.Name(), ) _, err = tmpFile.Write(content) @@ -1900,13 +1900,13 @@ storage: err = tmpCredsFile.Close() So(err, ShouldBeNil) - content = []byte(fmt.Sprintf(`{ "distSpecVersion": "1.1.1", + content = fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "/tmp/zot" }, "http": { "address": "127.0.0.1", "port": "8080", "auth": { "ldap": { "credentialsFile": "%v", "address": "ldap.example.org", "port": 389, "startTLS": false, "baseDN": "ou=Users,dc=example,dc=org", "userAttribute": "uid", "userGroupAttribute": "memberOf", "skipVerify": true, "subtreeSearch": true }, "failDelay": 5 } }, "log": { "level": "debug" } }`, - tmpCredsFile.Name()), + tmpCredsFile.Name(), ) _, err = tmpFile.Write(content) @@ -1945,12 +1945,12 @@ func TestApiKeyConfig(t *testing.T) { defer os.Remove(tmpfile.Name()) - content = []byte(fmt.Sprintf(`{"distSpecVersion":"1.1.1","storage":{"rootDirectory":"/tmp/zot"}, + content = fmt.Appendf([]byte{}, `{"distSpecVersion":"1.1.1","storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"openid":{"providers":{"oidc":{"issuer":"http://127.0.0.1:5556/dex", "credentialsFile":"%s","scopes":["openid"]}}}}}, "log":{"level":"debug"}}`, - tmpCredsFile.Name()), + tmpCredsFile.Name(), ) err = os.WriteFile(tmpfile.Name(), content, 0o0600) @@ -2349,7 +2349,7 @@ func TestScrub(t *testing.T) { defer os.Remove(tmpfile.Name()) // clean up - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "storage": { "rootDirectory": "%s" }, @@ -2360,7 +2360,7 @@ func TestScrub(t *testing.T) { "level": "debug" } } - `, dir, port)) + `, dir, port) _, err = tmpfile.Write(content) So(err, ShouldBeNil) err = tmpfile.Close() @@ -2381,7 +2381,7 @@ func TestScrub(t *testing.T) { defer os.Remove(tmpfile.Name()) // clean up - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "storage": { "rootDirectory": "" }, @@ -2392,7 +2392,7 @@ func TestScrub(t *testing.T) { "level": "debug" } } - `, port)) + `, port) _, err = tmpfile.Write(content) So(err, ShouldBeNil) err = tmpfile.Close() @@ -2438,7 +2438,7 @@ func TestScrub(t *testing.T) { defer os.Remove(tmpfile.Name()) // clean up - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "storage": { "rootDirectory": "%s" }, @@ -2449,7 +2449,7 @@ func TestScrub(t *testing.T) { "level": "debug" } } - `, dir, port)) + `, dir, port) _, err = tmpfile.Write(content) So(err, ShouldBeNil) err = tmpfile.Close() @@ -2548,7 +2548,7 @@ func TestClusterConfig(t *testing.T) { baseExamplePath := "../../../examples/scale-out-cluster-cloud/" Convey("Should successfully load example configs for cloud", t, func() { - for memberIdx := 0; memberIdx < 3; memberIdx++ { + for memberIdx := range 3 { cfgFileToLoad := fmt.Sprintf("%s/config-cluster-member%d.json", baseExamplePath, memberIdx) cfg := config.New() err := cli.LoadConfiguration(cfg, cfgFileToLoad) @@ -2557,7 +2557,7 @@ func TestClusterConfig(t *testing.T) { }) Convey("Should successfully load example TLS configs for cloud", t, func() { - for memberIdx := 0; memberIdx < 3; memberIdx++ { + for memberIdx := range 3 { cfgFileToLoad := fmt.Sprintf("%s/tls/config-cluster-member%d.json", baseExamplePath, memberIdx) cfg := config.New() err := cli.LoadConfiguration(cfg, cfgFileToLoad) @@ -2719,6 +2719,7 @@ func runCLIWithConfig(tempDir string, config string) (string, error) { // Run CLI in a goroutine, but handle errors via a channel errCh := make(chan error, 1) + go func() { errCh <- cli.NewServerRootCmd().Execute() }() diff --git a/pkg/cli/server/stress_test.go b/pkg/cli/server/stress_test.go index 79c2c4df..8791cb49 100644 --- a/pkg/cli/server/stress_test.go +++ b/pkg/cli/server/stress_test.go @@ -1,5 +1,4 @@ //go:build stress -// +build stress package server_test @@ -64,6 +63,7 @@ func TestStressTooManyOpenFiles(t *testing.T) { defer func() { // list the content of the directory (useful in case of test fail) + //nolint: noctx // old code, no context available out, err := exec.Command("du", "-ab", dir).Output() if err != nil { t.Logf("error when listing storage files:\n%s\n", err) @@ -108,6 +108,7 @@ func TestStressTooManyOpenFiles(t *testing.T) { "docker://public.ecr.aws/zomato/alpine:3.11.3", fmt.Sprintf("oci:%s:alpine", dir), } + //nolint: noctx // old code, no context available out, err := exec.Command("skopeo", skopeoArgs...).Output() if err != nil { t.Logf("\nerror on skopeo copy:\n%s\n", err) @@ -178,6 +179,7 @@ func worker(id int, zotPort, rootDir string) { sourceImg, destImg, } + //nolint: noctx // old code, no context available err := exec.Command("skopeo", skopeoArgs...).Run() if err != nil { //nolint: wsl continue // we expect clients to receive errors due to FD limit reached on server diff --git a/pkg/cli/server/validate_sync_disabled.go b/pkg/cli/server/validate_sync_disabled.go index 8c5da849..f1e42e65 100644 --- a/pkg/cli/server/validate_sync_disabled.go +++ b/pkg/cli/server/validate_sync_disabled.go @@ -1,5 +1,4 @@ //go:build !sync -// +build !sync package server diff --git a/pkg/cli/server/validate_sync_enabled.go b/pkg/cli/server/validate_sync_enabled.go index cd2aa69c..d81ff39e 100644 --- a/pkg/cli/server/validate_sync_enabled.go +++ b/pkg/cli/server/validate_sync_enabled.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package server diff --git a/pkg/cli/server/verify_retention.go b/pkg/cli/server/verify_retention.go index 95984e86..4b74b84b 100644 --- a/pkg/cli/server/verify_retention.go +++ b/pkg/cli/server/verify_retention.go @@ -113,6 +113,7 @@ func newVerifyFeatureRetentionCmd(conf *config.Config) *cobra.Command { // Initialize MetaDB only if retention policies are configured var metaDB mTypes.MetaDB + if conf.IsRetentionEnabled() { // Enable retention dry-run mode only when retention is enabled conf.Storage.Retention.DryRun = true @@ -164,8 +165,10 @@ func newVerifyFeatureRetentionCmd(conf *config.Config) *cobra.Command { return fmt.Errorf("failed to get timeout flag: %w", err) } - var waitCtx context.Context - var cancel context.CancelFunc + var ( + waitCtx context.Context + cancel context.CancelFunc + ) if timeout > 0 { logger.Info().Dur("timeout", timeout).Msg("waiting for garbage collection tasks to complete...") diff --git a/pkg/cli/server/verify_retention_test.go b/pkg/cli/server/verify_retention_test.go index 7307deaf..563a0c7c 100644 --- a/pkg/cli/server/verify_retention_test.go +++ b/pkg/cli/server/verify_retention_test.go @@ -80,7 +80,7 @@ func TestRetentionCheckNegative(t *testing.T) { logFile := path.Join(testDir, "retention-check.log") port := GetFreePort() - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "%s", @@ -90,7 +90,7 @@ func TestRetentionCheckNegative(t *testing.T) { "address": "127.0.0.1", "port": "%s" } - }`, testDir, port)) + }`, testDir, port) err := os.WriteFile(configFile, content, 0o600) So(err, ShouldBeNil) @@ -128,7 +128,7 @@ func TestRetentionCheckNegative(t *testing.T) { defer ctrlManager.StopServer() - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "storage": { "rootDirectory": "%s", "gc": true, @@ -154,7 +154,7 @@ func TestRetentionCheckNegative(t *testing.T) { "level": "debug" } } - `, storageDir, port)) + `, storageDir, port) err := os.WriteFile(configFile, content, 0o600) So(err, ShouldBeNil) @@ -187,7 +187,7 @@ func TestRetentionCheckNegative(t *testing.T) { configFile := path.Join(testDir, "zot-config.json") port := GetFreePort() - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "%s", @@ -197,7 +197,7 @@ func TestRetentionCheckNegative(t *testing.T) { "address": "127.0.0.1", "port": "%s" } - }`, testDir, port)) + }`, testDir, port) err := os.WriteFile(configFile, content, 0o600) So(err, ShouldBeNil) @@ -227,7 +227,7 @@ func TestRetentionCheckNegative(t *testing.T) { logFile := path.Join(testDir, "retention-check.log") port := GetFreePort() - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "%s", @@ -237,7 +237,7 @@ func TestRetentionCheckNegative(t *testing.T) { "address": "127.0.0.1", "port": "%s" } - }`, testDir, port)) + }`, testDir, port) err := os.WriteFile(configFile, content, 0o600) So(err, ShouldBeNil) @@ -275,7 +275,7 @@ func TestRetentionCheckWithRetentionEnabledAndRedisDriver(t *testing.T) { configFile := path.Join(testDir, "zot-config.json") logFile := path.Join(testDir, "retention-check.log") - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "%s", @@ -310,7 +310,7 @@ func TestRetentionCheckWithRetentionEnabledAndRedisDriver(t *testing.T) { "level": "debug" } } - `, storageDir, testGCDelay, miniRedis.Addr(), port)) + `, storageDir, testGCDelay, miniRedis.Addr(), port) err := os.WriteFile(configFile, content, 0o600) So(err, ShouldBeNil) @@ -513,7 +513,7 @@ func TestRetentionCheckWithRetentionEnabled(t *testing.T) { configFile := path.Join(testDir, "zot-config.json") logFile := path.Join(testDir, "retention-check.log") - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "%s", @@ -543,7 +543,7 @@ func TestRetentionCheckWithRetentionEnabled(t *testing.T) { "level": "debug" } } - `, storageDir, testGCDelay, port)) + `, storageDir, testGCDelay, port) err := os.WriteFile(configFile, content, 0o600) So(err, ShouldBeNil) @@ -804,7 +804,7 @@ func TestRetentionCheckWithDeleteReferrers(t *testing.T) { configFile := path.Join(testDir, "zot-config.json") logFile := path.Join(testDir, "retention-check.log") - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "%s", @@ -835,7 +835,7 @@ func TestRetentionCheckWithDeleteReferrers(t *testing.T) { "level": "debug" } } - `, storageDir, testGCDelay, port)) + `, storageDir, testGCDelay, port) err := os.WriteFile(configFile, content, 0o600) So(err, ShouldBeNil) @@ -985,7 +985,7 @@ func TestRetentionCheckWithRetentionDisabled(t *testing.T) { configFile := path.Join(testDir, "zot-config.json") logFile := path.Join(testDir, "retention-check.log") - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "%s", @@ -1001,7 +1001,7 @@ func TestRetentionCheckWithRetentionDisabled(t *testing.T) { "level": "debug" } } - `, storageDir, testGCDelay, port)) + `, storageDir, testGCDelay, port) err := os.WriteFile(configFile, content, 0o600) So(err, ShouldBeNil) @@ -1141,7 +1141,7 @@ func TestRetentionCheckWithSubpaths(t *testing.T) { configFile := path.Join(testDir, "zot-config.json") logFile := path.Join(testDir, "retention-check.log") - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "%s", @@ -1195,7 +1195,7 @@ func TestRetentionCheckWithSubpaths(t *testing.T) { "level": "debug" } } - `, storageDir, testGCDelay, storageDir, testGCDelay, port)) + `, storageDir, testGCDelay, storageDir, testGCDelay, port) err := os.WriteFile(configFile, content, 0o600) So(err, ShouldBeNil) @@ -1442,7 +1442,7 @@ func TestRetentionCheckWithGCIntervalOverride(t *testing.T) { logFile := path.Join(testDir, "retention-check.log") port := GetFreePort() - content := []byte(fmt.Sprintf(`{ + content := fmt.Appendf([]byte{}, `{ "distSpecVersion": "1.1.1", "storage": { "rootDirectory": "%s", @@ -1466,7 +1466,7 @@ func TestRetentionCheckWithGCIntervalOverride(t *testing.T) { "level": "debug" } } - `, storageDir, testGCDelay, storageDir, testGCDelay, port)) + `, storageDir, testGCDelay, storageDir, testGCDelay, port) err := os.WriteFile(configFile, content, 0o600) So(err, ShouldBeNil) @@ -1506,10 +1506,10 @@ func TestRetentionCheckWithGCIntervalOverride(t *testing.T) { //nolint:tagliatelle // JSON field names match Go struct names type ConfigParams struct { Storage struct { - GCInterval int64 `json:"GCInterval"` - GCDelay int64 `json:"GCDelay"` - GCMaxSchedulerDelay int64 `json:"GCMaxSchedulerDelay"` - SubPaths map[string]interface{} `json:"SubPaths"` + GCInterval int64 `json:"GCInterval"` + GCDelay int64 `json:"GCDelay"` + GCMaxSchedulerDelay int64 `json:"GCMaxSchedulerDelay"` + SubPaths map[string]any `json:"SubPaths"` } `json:"Storage"` } diff --git a/pkg/cluster/cluster.go b/pkg/cluster/cluster.go index c97395d4..9f00abb1 100644 --- a/pkg/cluster/cluster.go +++ b/pkg/cluster/cluster.go @@ -2,8 +2,8 @@ package cluster import "github.com/dchest/siphash" -// computes the target member using siphash and returns the index and the member -// siphash was chosen to prevent against hash attacks where an attacker +// ComputeTargetMember computes the target member using SipHash and returns the index and the member. +// SipHash was chosen to prevent against hash attacks where an attacker // can target all requests to one given instance instead of balancing across the cluster // resulting in a Denial-of-Service (DOS). // ref: https://en.wikipedia.org/wiki/SipHash diff --git a/pkg/common/common.go b/pkg/common/common.go index 3fe2a81f..20cddccc 100644 --- a/pkg/common/common.go +++ b/pkg/common/common.go @@ -9,6 +9,7 @@ import ( "net" "os" "regexp" + "slices" "strings" "syscall" "time" @@ -26,7 +27,8 @@ const ( CosignSignature = "cosign" CosignSigKey = "dev.cosignproject.cosign/signature" NotationSignature = "notation" - // same value as github.com/notaryproject/notation-go/registry.ArtifactTypeNotation (assert by internal test). + // ArtifactTypeNotation is the same value as github.com/notaryproject/notation-go/registry.ArtifactTypeNotation + // (assert by internal test). // reason used: to reduce zot minimal binary size (otherwise adds oras.land/oras-go/v2 deps). ArtifactTypeNotation = "application/vnd.cncf.notary.signature" ArtifactTypeCosign = "application/vnd.dev.cosign.artifact.sig.v1+json" @@ -51,28 +53,7 @@ func IsCosignTag(tag string) bool { return IsCosignSignature(tag) || IsCosignSBOM(tag) } -func Contains[T comparable](elems []T, v T) bool { - for _, s := range elems { - if v == s { - return true - } - } - - return false -} - -// first match of item in []. -func Index(slice []string, item string) int { - for k, v := range slice { - if item == v { - return k - } - } - - return -1 -} - -// remove matches of item in []. +// RemoveFrom removes matches of item in []. func RemoveFrom(inputSlice []string, item string) []string { var newSlice []string @@ -85,7 +66,7 @@ func RemoveFrom(inputSlice []string, item string) []string { return newSlice } -func TypeOf(v interface{}) string { +func TypeOf(v any) string { return fmt.Sprintf("%T", v) } @@ -113,8 +94,8 @@ func DirExists(d string) bool { return true } -// Used to filter a json fields by using an intermediate struct. -func MarshalThroughStruct(obj interface{}, throughStruct interface{}) ([]byte, error) { +// MarshalThroughStruct is used to filter a json fields by using an intermediate struct. +func MarshalThroughStruct(obj any, throughStruct any) ([]byte, error) { toJSON, err := json.Marshal(obj) if err != nil { return []byte{}, err @@ -134,16 +115,12 @@ func MarshalThroughStruct(obj interface{}, throughStruct interface{}) ([]byte, e } func ContainsStringIgnoreCase(strSlice []string, str string) bool { - for _, val := range strSlice { - if strings.EqualFold(val, str) { - return true - } - } - - return false + return slices.ContainsFunc(strSlice, func(val string) bool { + return strings.EqualFold(val, str) + }) } -// this function will check if tag is a referrers tag +// IsReferrersTag checks if tag is a referrers tag // (https://github.com/opencontainers/distribution-spec/blob/main/spec.md#referrers-tag-schema). func IsReferrersTag(tag string) bool { referrersTagRule := regexp.MustCompile(`sha256\-[A-Za-z0-9]*$`) @@ -160,7 +137,7 @@ func IsContextDone(ctx context.Context) bool { } } -// get a list of IP addresses configured on the host's +// GetLocalIPs gets a list of IP addresses configured on the host's // interfaces. func GetLocalIPs() ([]string, error) { var localIPs []string @@ -186,7 +163,7 @@ func GetLocalIPs() ([]string, error) { return localIPs, nil } -// get a list of listening sockets on the host (IP:port). +// GetLocalSockets gets a list of listening sockets on the host (IP:port). // IPv6 is returned as [host]:port. func GetLocalSockets(port string) ([]string, error) { localIPs, err := GetLocalIPs() @@ -205,7 +182,7 @@ func GetLocalSockets(port string) ([]string, error) { } func GetIPFromHostName(host string) ([]string, error) { - addrs, err := net.LookupIP(host) + addrs, err := net.LookupIP(host) //nolint: noctx if err != nil { return []string{}, err } @@ -219,7 +196,7 @@ func GetIPFromHostName(host string) ([]string, error) { return ips, nil } -// checks if 2 sockets are equal at the host port level. +// AreSocketsEqual checks if 2 sockets are equal at the host port level. func AreSocketsEqual(socketA string, socketB string) (bool, error) { hostA, portA, err := net.SplitHostPort(socketA) if err != nil { diff --git a/pkg/common/common_test.go b/pkg/common/common_test.go index 5dbb8773..2b255032 100644 --- a/pkg/common/common_test.go +++ b/pkg/common/common_test.go @@ -3,6 +3,7 @@ package common_test import ( "os" "path" + "slices" "strings" "testing" @@ -16,9 +17,9 @@ import ( func TestCommon(t *testing.T) { Convey("test Contains()", t, func() { first := []string{"apple", "biscuit"} - So(common.Contains(first, "apple"), ShouldBeTrue) - So(common.Contains(first, "peach"), ShouldBeFalse) - So(common.Contains([]string{}, "apple"), ShouldBeFalse) + So(slices.Contains(first, "apple"), ShouldBeTrue) + So(slices.Contains(first, "peach"), ShouldBeFalse) + So(slices.Contains([]string{}, "apple"), ShouldBeFalse) }) Convey("test MarshalThroughStruct()", t, func() { @@ -56,11 +57,6 @@ func TestCommon(t *testing.T) { So(isDir, ShouldBeFalse) }) - Convey("Index func", t, func() { - So(common.Index([]string{"a", "b"}, "b"), ShouldEqual, 1) - So(common.Index([]string{"a", "b"}, "c"), ShouldEqual, -1) - }) - Convey("Test ArtifactTypeNotation const has same value as in notaryproject", t, func() { So(common.ArtifactTypeNotation, ShouldEqual, notreg.ArtifactTypeNotation) }) diff --git a/pkg/common/http_client.go b/pkg/common/http_client.go index 58c77252..dd9e33b4 100644 --- a/pkg/common/http_client.go +++ b/pkg/common/http_client.go @@ -56,14 +56,14 @@ func loadPerHostCerts(caCertPool *x509.CertPool, host string) *tls.Config { return nil } -// Holds certificate options for an HTTP client. +// HTTPClientCertOptions holds certificate options for an HTTP client. type HTTPClientCertOptions struct { ClientCertFile string // Holds the path to the client certificate file. Mandatory if ClientKeyFile is present. ClientKeyFile string // Holds the path to the client key file. Mandatory if ClientCertFile is present. RootCaCertFile string // Optional. Holds the path to the custom Root CA cert file. } -// Holds client options for creating an HTTP client. +// HTTPClientOptions holds client options for creating an HTTP client. type HTTPClientOptions struct { // Results in a client with TLS config if true. TLSEnabled bool diff --git a/pkg/common/http_server.go b/pkg/common/http_server.go index e29edf0d..0b1d6e30 100644 --- a/pkg/common/http_server.go +++ b/pkg/common/http_server.go @@ -129,7 +129,7 @@ func AuthzFail(w http.ResponseWriter, r *http.Request, identity, realm string, d } } -func WriteJSON(response http.ResponseWriter, status int, data interface{}) { +func WriteJSON(response http.ResponseWriter, status int, data any) { json := jsoniter.ConfigCompatibleWithStandardLibrary body, err := json.Marshal(data) diff --git a/pkg/common/model.go b/pkg/common/model.go index 596e9967..ab3ad6a9 100644 --- a/pkg/common/model.go +++ b/pkg/common/model.go @@ -137,8 +137,9 @@ type Annotation struct { } type ImageListWithCVEFixedResponse struct { - Errors []ErrorGQL `json:"errors"` ImageListWithCVEFixed `json:"data"` + + Errors []ErrorGQL `json:"errors"` } type ImageListWithCVEFixed struct { @@ -146,8 +147,9 @@ type ImageListWithCVEFixed struct { } type ImagesForCve struct { - Errors []ErrorGQL `json:"errors"` ImagesForCVEList `json:"data"` + + Errors []ErrorGQL `json:"errors"` } type ImagesForCVEList struct { @@ -155,8 +157,9 @@ type ImagesForCVEList struct { } type ImagesForDigest struct { - Errors []ErrorGQL `json:"errors"` ImagesForDigestList `json:"data"` + + Errors []ErrorGQL `json:"errors"` } type ImagesForDigestList struct { @@ -165,17 +168,20 @@ type ImagesForDigestList struct { type RepoWithNewestImageResponse struct { RepoListWithNewestImage `json:"data"` - Errors []ErrorGQL `json:"errors"` + + Errors []ErrorGQL `json:"errors"` } type DerivedImageListResponse struct { DerivedImageList `json:"data"` - Errors []ErrorGQL `json:"errors"` + + Errors []ErrorGQL `json:"errors"` } type BaseImageListResponse struct { BaseImageList `json:"data"` - Errors []ErrorGQL `json:"errors"` + + Errors []ErrorGQL `json:"errors"` } type DerivedImageList struct { @@ -188,7 +194,8 @@ type BaseImageList struct { type ImageListResponse struct { ImageList `json:"data"` - Errors []ErrorGQL `json:"errors"` + + Errors []ErrorGQL `json:"errors"` } type ImageList struct { @@ -197,12 +204,14 @@ type ImageList struct { type ExpandedRepoInfoResp struct { ExpandedRepoInfo `json:"data"` - Errors []ErrorGQL `json:"errors"` + + Errors []ErrorGQL `json:"errors"` } type ReferrersResp struct { ReferrersResult `json:"data"` - Errors []ErrorGQL `json:"errors"` + + Errors []ErrorGQL `json:"errors"` } type ReferrersResult struct { @@ -210,7 +219,8 @@ type ReferrersResult struct { } type GlobalSearchResultResp struct { GlobalSearchResult `json:"data"` - Errors []ErrorGQL `json:"errors"` + + Errors []ErrorGQL `json:"errors"` } type GlobalSearchResult struct { @@ -248,7 +258,8 @@ type SingleImageSummary struct { } type ImageSummaryResult struct { SingleImageSummary `json:"data"` - Errors []ErrorGQL `json:"errors"` + + Errors []ErrorGQL `json:"errors"` } //nolint:tagliatelle // graphQL schema @@ -263,12 +274,14 @@ type BookmarkedRepos struct { type StarredReposResponse struct { StarredRepos `json:"data"` - Errors []ErrorGQL `json:"errors"` + + Errors []ErrorGQL `json:"errors"` } type BookmarkedReposResponse struct { BookmarkedRepos `json:"data"` - Errors []ErrorGQL `json:"errors"` + + Errors []ErrorGQL `json:"errors"` } type ImageTags struct { diff --git a/pkg/compat/compat.go b/pkg/compat/compat.go index 62801697..fc532902 100644 --- a/pkg/compat/compat.go +++ b/pkg/compat/compat.go @@ -1,6 +1,8 @@ package compat import ( + "slices" + dockerList "github.com/distribution/distribution/v3/manifest/manifestlist" docker "github.com/distribution/distribution/v3/manifest/schema2" v1 "github.com/opencontainers/image-spec/specs-go/v1" @@ -22,13 +24,7 @@ func CompatibleManifestMediaTypes() []string { } func IsCompatibleManifestMediaType(mediatype string) bool { - for _, mt := range CompatibleManifestMediaTypes() { - if mt == mediatype { - return true - } - } - - return false + return slices.Contains(CompatibleManifestMediaTypes(), mediatype) } func CompatibleManifestListMediaTypes() []string { @@ -36,13 +32,7 @@ func CompatibleManifestListMediaTypes() []string { } func IsCompatibleManifestListMediaType(mediatype string) bool { - for _, mt := range CompatibleManifestListMediaTypes() { - if mt == mediatype { - return true - } - } - - return false + return slices.Contains(CompatibleManifestListMediaTypes(), mediatype) } func CompatibleConfigMediaTypes() []string { @@ -50,13 +40,7 @@ func CompatibleConfigMediaTypes() []string { } func IsCompatibleConfigMediaType(mediatype string) bool { - for _, mt := range CompatibleConfigMediaTypes() { - if mt == mediatype { - return true - } - } - - return false + return slices.Contains(CompatibleConfigMediaTypes(), mediatype) } func Validate(body []byte, mediaType string) ([]v1.Descriptor, error) { diff --git a/pkg/compliance/v1_0_0/check.go b/pkg/compliance/v1_0_0/check.go index ef0bb926..e701e1e5 100644 --- a/pkg/compliance/v1_0_0/check.go +++ b/pkg/compliance/v1_0_0/check.go @@ -901,7 +901,7 @@ func outputJSONExit() { } func validateMinifyRawJSON(rawJSON string) string { - var jsonData interface{} + var jsonData any err := json.Unmarshal([]byte(rawJSON), &jsonData) if err != nil { diff --git a/pkg/debug/gqlplayground/gqlplayground.go b/pkg/debug/gqlplayground/gqlplayground.go index e119021c..47be8bc5 100644 --- a/pkg/debug/gqlplayground/gqlplayground.go +++ b/pkg/debug/gqlplayground/gqlplayground.go @@ -1,5 +1,4 @@ //go:build debug -// +build debug package debug diff --git a/pkg/debug/gqlplayground/gqlplayground_disabled.go b/pkg/debug/gqlplayground/gqlplayground_disabled.go index c6006546..cfd1ad47 100644 --- a/pkg/debug/gqlplayground/gqlplayground_disabled.go +++ b/pkg/debug/gqlplayground/gqlplayground_disabled.go @@ -1,5 +1,4 @@ //go:build !debug -// +build !debug package debug diff --git a/pkg/debug/pprof/pprof.go b/pkg/debug/pprof/pprof.go index ce37c7dc..b77e430e 100644 --- a/pkg/debug/pprof/pprof.go +++ b/pkg/debug/pprof/pprof.go @@ -1,5 +1,4 @@ //go:build profile -// +build profile package pprof diff --git a/pkg/debug/pprof/pprof_disabled.go b/pkg/debug/pprof/pprof_disabled.go index 8a907db0..a4d16dca 100644 --- a/pkg/debug/pprof/pprof_disabled.go +++ b/pkg/debug/pprof/pprof_disabled.go @@ -1,5 +1,4 @@ //go:build !profile -// +build !profile package pprof diff --git a/pkg/debug/pprof/pprof_test.go b/pkg/debug/pprof/pprof_test.go index a297640c..35748e66 100644 --- a/pkg/debug/pprof/pprof_test.go +++ b/pkg/debug/pprof/pprof_test.go @@ -1,5 +1,4 @@ //go:build profile -// +build profile package pprof_test diff --git a/pkg/debug/swagger/swagger.go b/pkg/debug/swagger/swagger.go index 6f0761c7..e423f0a5 100644 --- a/pkg/debug/swagger/swagger.go +++ b/pkg/debug/swagger/swagger.go @@ -1,5 +1,4 @@ //go:build debug -// +build debug // @contact.name API Support // @contact.url http://www.swagger.io/support @@ -7,12 +6,14 @@ package debug +//nolint:gci // import order required by swaggo import ( "github.com/gorilla/mux" httpSwagger "github.com/swaggo/http-swagger" "zotregistry.dev/zot/v2/pkg/api/config" "zotregistry.dev/zot/v2/pkg/log" //nolint:goimports + // as required by swaggo. _ "zotregistry.dev/zot/v2/swagger" ) diff --git a/pkg/debug/swagger/swagger_disabled.go b/pkg/debug/swagger/swagger_disabled.go index a5b85239..20204676 100644 --- a/pkg/debug/swagger/swagger_disabled.go +++ b/pkg/debug/swagger/swagger_disabled.go @@ -1,5 +1,4 @@ //go:build !debug -// +build !debug // @contact.name API Support // @contact.url http://www.swagger.io/support diff --git a/pkg/exporter/api/config.go b/pkg/exporter/api/config.go index e5cbb911..36dc69b5 100644 --- a/pkg/exporter/api/config.go +++ b/pkg/exporter/api/config.go @@ -1,9 +1,8 @@ //go:build !metrics -// +build !metrics package api -// We export below types in order for cli package to be able to read it from configuration file. +// LogConfig and the other types below are exported so the cli package can read them from configuration file. type LogConfig struct { Level string Output string diff --git a/pkg/exporter/api/controller.go b/pkg/exporter/api/controller.go index 1da96c40..922642f2 100644 --- a/pkg/exporter/api/controller.go +++ b/pkg/exporter/api/controller.go @@ -1,5 +1,4 @@ //go:build !metrics -// +build !metrics package api diff --git a/pkg/exporter/api/controller_test.go b/pkg/exporter/api/controller_test.go index 92d62359..e97f438b 100644 --- a/pkg/exporter/api/controller_test.go +++ b/pkg/exporter/api/controller_test.go @@ -1,5 +1,4 @@ //go:build !metrics -// +build !metrics package api_test @@ -53,6 +52,7 @@ func TestNew(t *testing.T) { func isChannelDrained(ch chan prometheus.Metric) bool { time.Sleep(SleepTime) + select { case <-ch: return false @@ -230,7 +230,7 @@ func TestNewExporter(t *testing.T) { } reqsSize := int(nBig.Int64()) - for i := 0; i < reqsSize; i++ { + for range reqsSize { monitoring.IncDownloadCounter(serverController.Metrics, "dummyrepo") } @@ -317,7 +317,7 @@ func TestNewExporter(t *testing.T) { } reqsSize := int(nBig.Int64()) - for i := 0; i < reqsSize; i++ { + for range reqsSize { latency := getRandomLatency() latencySum += latency.Seconds() monitoring.ObserveHTTPRepoLatency(serverController.Metrics, "/v2/dummyrepo/manifests/testreference", latency) @@ -505,7 +505,7 @@ func TestNewExporter(t *testing.T) { } workersSize := int(nBig.Int64()) - for i := 0; i < workersSize; i++ { + for range workersSize { wg.Add(1) go func() { diff --git a/pkg/exporter/api/exporter.go b/pkg/exporter/api/exporter.go index 8b72ac3d..8d144b51 100644 --- a/pkg/exporter/api/exporter.go +++ b/pkg/exporter/api/exporter.go @@ -1,5 +1,4 @@ //go:build !metrics -// +build !metrics //nolint:varnamelen package api @@ -30,14 +29,14 @@ type Collector struct { invalidChars *regexp.Regexp } -// Implements prometheus.Collector interface. +// Describe implements prometheus.Collector interface. func (zc Collector) Describe(ch chan<- *prometheus.Desc) { for _, metricDescription := range zc.MetricsDesc { ch <- metricDescription } } -// Implements prometheus.Collector interface. +// Collect implements prometheus.Collector interface. func (zc Collector) Collect(ch chan<- prometheus.Metric) { metrics, err := zc.Client.GetMetrics() if err != nil { diff --git a/pkg/exporter/cli/cli.go b/pkg/exporter/cli/cli.go index 59c2ec33..05f971c1 100644 --- a/pkg/exporter/cli/cli.go +++ b/pkg/exporter/cli/cli.go @@ -1,5 +1,4 @@ //go:build !metrics -// +build !metrics package cli diff --git a/pkg/exporter/cli/cli_test.go b/pkg/exporter/cli/cli_test.go index 071b3fb6..61d5e8d6 100644 --- a/pkg/exporter/cli/cli_test.go +++ b/pkg/exporter/cli/cli_test.go @@ -1,5 +1,4 @@ //go:build !metrics -// +build !metrics package cli_test diff --git a/pkg/extensions/config/config.go b/pkg/extensions/config/config.go index 20bf8b7f..d05e11bd 100644 --- a/pkg/extensions/config/config.go +++ b/pkg/extensions/config/config.go @@ -27,8 +27,9 @@ type ExtensionConfig struct { type ImageTrustConfig struct { BaseConfig `mapstructure:",squash"` - Cosign bool - Notation bool + + Cosign bool + Notation bool } type APIKeyConfig struct { @@ -40,13 +41,15 @@ type MgmtConfig struct { } type LintConfig struct { - BaseConfig `mapstructure:",squash"` + BaseConfig `mapstructure:",squash"` + MandatoryAnnotations []string } type SearchConfig struct { BaseConfig `mapstructure:",squash"` - CVE *CVEConfig + + CVE *CVEConfig } type CVEConfig struct { @@ -61,6 +64,7 @@ type TrivyConfig struct { type MetricsConfig struct { BaseConfig `mapstructure:",squash"` + Prometheus *PrometheusConfig } @@ -70,7 +74,8 @@ type PrometheusConfig struct { type ScrubConfig struct { BaseConfig `mapstructure:",squash"` - Interval time.Duration + + Interval time.Duration } type UIConfig struct { diff --git a/pkg/extensions/config/config_test.go b/pkg/extensions/config/config_test.go index a43069dd..c174b8b7 100644 --- a/pkg/extensions/config/config_test.go +++ b/pkg/extensions/config/config_test.go @@ -216,7 +216,7 @@ func testConcurrentAccessWithConfig( done := make(chan bool, 10) errors := make(chan error, 10) - for i := 0; i < 10; i++ { + for range 10 { go func() { defer func() { if r := recover(); r != nil { @@ -229,7 +229,7 @@ func testConcurrentAccessWithConfig( done <- true }() - for j := 0; j < 100; j++ { + for range 100 { result := testFunc(extensionConfig) if !result { errors <- expectedError @@ -241,7 +241,7 @@ func testConcurrentAccessWithConfig( } // Wait for all goroutines to complete - for i := 0; i < 10; i++ { + for range 10 { <-done } @@ -448,7 +448,7 @@ func TestExtensionConfig(t *testing.T) { errors := make(chan error, 15) // Launch goroutines for each method - for i := 0; i < 5; i++ { + for range 5 { go func() { defer func() { if r := recover(); r != nil { @@ -461,7 +461,7 @@ func TestExtensionConfig(t *testing.T) { done <- true }() - for j := 0; j < 50; j++ { + for range 50 { result := extensionConfig.IsSearchEnabled() if !result { errors <- errIsSearchEnabledExpectedTrue @@ -472,7 +472,7 @@ func TestExtensionConfig(t *testing.T) { }() } - for i := 0; i < 5; i++ { + for range 5 { go func() { defer func() { if r := recover(); r != nil { @@ -485,7 +485,7 @@ func TestExtensionConfig(t *testing.T) { done <- true }() - for j := 0; j < 50; j++ { + for range 50 { result := extensionConfig.IsUIEnabled() if !result { errors <- errIsUIEnabledExpectedTrue @@ -496,7 +496,7 @@ func TestExtensionConfig(t *testing.T) { }() } - for i := 0; i < 5; i++ { + for range 5 { go func() { defer func() { if r := recover(); r != nil { @@ -509,7 +509,7 @@ func TestExtensionConfig(t *testing.T) { done <- true }() - for j := 0; j < 50; j++ { + for range 50 { result := extensionConfig.AreUserPrefsEnabled() if !result { errors <- errAreUserPrefsEnabledExpectedTrue @@ -521,7 +521,7 @@ func TestExtensionConfig(t *testing.T) { } // Wait for all goroutines to complete - for i := 0; i < 15; i++ { + for range 15 { <-done } diff --git a/pkg/extensions/config/events/config.go b/pkg/extensions/config/events/config.go index ad292ff4..41d0c0a4 100644 --- a/pkg/extensions/config/events/config.go +++ b/pkg/extensions/config/events/config.go @@ -35,6 +35,7 @@ type Config struct { type SinkConfig struct { *Credentials *TLSConfig + Type SinkType Address string Channel string diff --git a/pkg/extensions/config/events/decoder.go b/pkg/extensions/config/events/decoder.go index 10091f06..e101c2f5 100644 --- a/pkg/extensions/config/events/decoder.go +++ b/pkg/extensions/config/events/decoder.go @@ -10,17 +10,17 @@ import ( // SinkConfigDecoderHook provides a mapstructure hook for decoding SinkConfig interfaces. func SinkConfigDecoderHook() mapstructure.DecodeHookFunc { - return func(_ reflect.Type, target reflect.Type, data interface{}) (interface{}, error) { + return func(_ reflect.Type, target reflect.Type, data any) (any, error) { // Only apply this hook when converting to SinkConfig if target.Name() != "SinkConfig" { return data, nil } - if target != reflect.TypeOf((*SinkConfig)(nil)).Elem() { + if target != reflect.TypeFor[SinkConfig]() { return data, nil } - dataMap, ok := data.(map[string]interface{}) + dataMap, ok := data.(map[string]any) if !ok { return data, nil } diff --git a/pkg/extensions/config/sync/config.go b/pkg/extensions/config/sync/config.go index 644d3e54..e22e2f08 100644 --- a/pkg/extensions/config/sync/config.go +++ b/pkg/extensions/config/sync/config.go @@ -4,7 +4,7 @@ import ( "time" ) -// key is registry address. +// CredentialsFile is a map where key is registry address. type CredentialsFile map[string]Credentials type Credentials struct { diff --git a/pkg/extensions/events/builder.go b/pkg/extensions/events/builder.go index 524ad5cd..f3dddb6a 100644 --- a/pkg/extensions/events/builder.go +++ b/pkg/extensions/events/builder.go @@ -1,5 +1,4 @@ //go:build events -// +build events package events diff --git a/pkg/extensions/events/events.go b/pkg/extensions/events/events.go index 176b3e39..38e893a2 100644 --- a/pkg/extensions/events/events.go +++ b/pkg/extensions/events/events.go @@ -1,5 +1,4 @@ //go:build events -// +build events package events diff --git a/pkg/extensions/events/events_test.go b/pkg/extensions/events/events_test.go index b0c6805e..ca9804d5 100644 --- a/pkg/extensions/events/events_test.go +++ b/pkg/extensions/events/events_test.go @@ -1,5 +1,4 @@ //go:build events -// +build events package events_test diff --git a/pkg/extensions/events/extension.go b/pkg/extensions/events/extension.go index 59c2af7d..1f8c3645 100644 --- a/pkg/extensions/events/extension.go +++ b/pkg/extensions/events/extension.go @@ -1,5 +1,4 @@ //go:build events -// +build events package events diff --git a/pkg/extensions/events/http_sink.go b/pkg/extensions/events/http_sink.go index b50035ea..e7e6029e 100644 --- a/pkg/extensions/events/http_sink.go +++ b/pkg/extensions/events/http_sink.go @@ -1,5 +1,4 @@ //go:build events -// +build events package events @@ -18,6 +17,7 @@ import ( type HTTPSink struct { cloudevents.Client + config eventsconf.SinkConfig } @@ -133,7 +133,7 @@ func GetHTTPClientForConfig(config eventsconf.SinkConfig) (*http.Client, error) }, nil } -// Helper function for basic auth encoding. +// BasicAuth is a helper function for basic auth encoding. func BasicAuth(username, password string) string { auth := username + ":" + password diff --git a/pkg/extensions/events/http_sink_test.go b/pkg/extensions/events/http_sink_test.go index 8ea4c9ee..c46810a5 100644 --- a/pkg/extensions/events/http_sink_test.go +++ b/pkg/extensions/events/http_sink_test.go @@ -1,5 +1,4 @@ //go:build events -// +build events package events_test diff --git a/pkg/extensions/events/nats_sink.go b/pkg/extensions/events/nats_sink.go index 65452d86..29dbb190 100644 --- a/pkg/extensions/events/nats_sink.go +++ b/pkg/extensions/events/nats_sink.go @@ -1,5 +1,4 @@ //go:build events -// +build events package events @@ -18,6 +17,7 @@ import ( // NATSSink implements a CloudEvents sink that publishes to NATS. type NATSSink struct { cloudevents.Client + conn *nats.Conn config eventsconf.SinkConfig } diff --git a/pkg/extensions/events/nats_sink_test.go b/pkg/extensions/events/nats_sink_test.go index 6c79a7ec..e47f13fa 100644 --- a/pkg/extensions/events/nats_sink_test.go +++ b/pkg/extensions/events/nats_sink_test.go @@ -1,5 +1,4 @@ //go:build events -// +build events package events_test diff --git a/pkg/extensions/extension_events.go b/pkg/extensions/extension_events.go index 4e58ec95..e48ebd14 100644 --- a/pkg/extensions/extension_events.go +++ b/pkg/extensions/extension_events.go @@ -1,5 +1,4 @@ //go:build events -// +build events package extensions diff --git a/pkg/extensions/extension_events_disabled.go b/pkg/extensions/extension_events_disabled.go index 81d73d14..5661b462 100644 --- a/pkg/extensions/extension_events_disabled.go +++ b/pkg/extensions/extension_events_disabled.go @@ -1,5 +1,4 @@ //go:build !events -// +build !events package extensions diff --git a/pkg/extensions/extension_events_disabled_test.go b/pkg/extensions/extension_events_disabled_test.go index 3ae1882c..27c86685 100644 --- a/pkg/extensions/extension_events_disabled_test.go +++ b/pkg/extensions/extension_events_disabled_test.go @@ -1,5 +1,4 @@ //go:build !events -// +build !events package extensions_test diff --git a/pkg/extensions/extension_image_trust.go b/pkg/extensions/extension_image_trust.go index 1301fe46..d48545ea 100644 --- a/pkg/extensions/extension_image_trust.go +++ b/pkg/extensions/extension_image_trust.go @@ -1,5 +1,4 @@ //go:build imagetrust -// +build imagetrust package extensions @@ -74,7 +73,7 @@ type ImageTrust struct { Log log.Logger } -// Cosign handler godoc +// HandleCosignPublicKeyUpload godoc // @Summary Upload cosign public keys for verifying signatures // @Description Upload cosign public keys for verifying signatures // @Router /v2/_zot/ext/cosign [post] @@ -108,7 +107,7 @@ func (trust *ImageTrust) HandleCosignPublicKeyUpload(response http.ResponseWrite response.WriteHeader(http.StatusOK) } -// Notation handler godoc +// HandleNotationCertificateUpload godoc // @Summary Upload notation certificates for verifying signatures // @Description Upload notation certificates for verifying signatures // @Router /v2/_zot/ext/notation [post] diff --git a/pkg/extensions/extension_image_trust_disabled.go b/pkg/extensions/extension_image_trust_disabled.go index 1353905f..45e2d1f4 100644 --- a/pkg/extensions/extension_image_trust_disabled.go +++ b/pkg/extensions/extension_image_trust_disabled.go @@ -1,5 +1,4 @@ //go:build !imagetrust -// +build !imagetrust package extensions diff --git a/pkg/extensions/extension_image_trust_test.go b/pkg/extensions/extension_image_trust_test.go index 5533bfbc..43295fb6 100644 --- a/pkg/extensions/extension_image_trust_test.go +++ b/pkg/extensions/extension_image_trust_test.go @@ -1,5 +1,4 @@ //go:build search && imagetrust -// +build search,imagetrust package extensions_test @@ -118,7 +117,7 @@ func TestSignaturesAllowedMethodsHeader(t *testing.T) { func TestSignatureUploadAndVerificationLocal(t *testing.T) { Convey("test with local storage", t, func() { - var cacheDriverParams map[string]interface{} + var cacheDriverParams map[string]any RunSignatureUploadAndVerificationTests(t, cacheDriverParams) }) @@ -128,7 +127,7 @@ func TestSignatureUploadAndVerificationRedis(t *testing.T) { Convey("test with local storage and redis metadb", t, func() { miniRedis := miniredis.RunT(t) - cacheDriverParams := map[string]interface{}{ + cacheDriverParams := map[string]any{ "name": "redis", "url": "redis://" + miniRedis.Addr(), } @@ -152,7 +151,7 @@ func TestSignatureUploadAndVerificationAWS(t *testing.T) { imageMetaTablename := "imageMetaTable" + uuid.String() repoBlobsInfoTablename := "repoBlobsInfoTable" + uuid.String() - cacheDriverParams := map[string]interface{}{ + cacheDriverParams := map[string]any{ "name": "dynamodb", "endpoint": os.Getenv("DYNAMODBMOCK_ENDPOINT"), "region": "us-east-2", @@ -171,7 +170,7 @@ func TestSignatureUploadAndVerificationAWS(t *testing.T) { }) } -func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[string]interface{}) { //nolint: thelper +func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[string]any) { //nolint: thelper repo := "repo" tag := "0.0.1" certName := "test" diff --git a/pkg/extensions/extension_metrics.go b/pkg/extensions/extension_metrics.go index 8de32158..4ad39675 100644 --- a/pkg/extensions/extension_metrics.go +++ b/pkg/extensions/extension_metrics.go @@ -1,5 +1,4 @@ //go:build metrics -// +build metrics package extensions diff --git a/pkg/extensions/extension_metrics_disabled.go b/pkg/extensions/extension_metrics_disabled.go index cc6eabd5..36ca43e0 100644 --- a/pkg/extensions/extension_metrics_disabled.go +++ b/pkg/extensions/extension_metrics_disabled.go @@ -1,5 +1,4 @@ //go:build !metrics -// +build !metrics package extensions diff --git a/pkg/extensions/extension_mgmt.go b/pkg/extensions/extension_mgmt.go index db99a87c..3cad555c 100644 --- a/pkg/extensions/extension_mgmt.go +++ b/pkg/extensions/extension_mgmt.go @@ -1,5 +1,4 @@ //go:build mgmt -// +build mgmt package extensions @@ -113,7 +112,7 @@ type Mgmt struct { Log log.Logger } -// mgmtHandler godoc +// HandleGetConfig godoc // @Summary Get current server configuration // @Description Get current server configuration // @Router /v2/_zot/ext/mgmt [get] diff --git a/pkg/extensions/extension_mgmt_disabled.go b/pkg/extensions/extension_mgmt_disabled.go index dda8aa8f..7fdf13ff 100644 --- a/pkg/extensions/extension_mgmt_disabled.go +++ b/pkg/extensions/extension_mgmt_disabled.go @@ -1,5 +1,4 @@ //go:build !mgmt -// +build !mgmt package extensions diff --git a/pkg/extensions/extension_scrub.go b/pkg/extensions/extension_scrub.go index 9811d451..365fd2c8 100644 --- a/pkg/extensions/extension_scrub.go +++ b/pkg/extensions/extension_scrub.go @@ -1,5 +1,4 @@ //go:build scrub -// +build scrub package extensions diff --git a/pkg/extensions/extension_scrub_disabled.go b/pkg/extensions/extension_scrub_disabled.go index cd7a0969..80776d0d 100644 --- a/pkg/extensions/extension_scrub_disabled.go +++ b/pkg/extensions/extension_scrub_disabled.go @@ -1,5 +1,4 @@ //go:build !scrub -// +build !scrub package extensions diff --git a/pkg/extensions/extension_search.go b/pkg/extensions/extension_search.go index 8c5458ae..9c2a2576 100644 --- a/pkg/extensions/extension_search.go +++ b/pkg/extensions/extension_search.go @@ -1,5 +1,4 @@ //go:build search -// +build search package extensions diff --git a/pkg/extensions/extension_search_disabled.go b/pkg/extensions/extension_search_disabled.go index 2a4ebe28..e8710a77 100644 --- a/pkg/extensions/extension_search_disabled.go +++ b/pkg/extensions/extension_search_disabled.go @@ -1,5 +1,4 @@ //go:build !search -// +build !search package extensions @@ -13,7 +12,7 @@ import ( "zotregistry.dev/zot/v2/pkg/storage" ) -type CveScanner interface{} +type CveScanner any func GetCveScanner(config *config.Config, storeController storage.StoreController, metaDB mTypes.MetaDB, log log.Logger, diff --git a/pkg/extensions/extension_sync.go b/pkg/extensions/extension_sync.go index 9ffaf29f..4041a7a4 100644 --- a/pkg/extensions/extension_sync.go +++ b/pkg/extensions/extension_sync.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package extensions @@ -140,7 +139,7 @@ func removeSelfURLs(httpAddress, httpPort string, registryConfig *syncconf.Regis } // check dns - ips, err := net.LookupIP(url.Hostname()) + ips, err := net.LookupIP(url.Hostname()) //nolint: noctx if err != nil { // will not remove, maybe it will get resolved later after multiple retries log.Warn().Str("url", registryURL).Msg("failed to lookup sync registry url's hostname") diff --git a/pkg/extensions/extension_sync_disabled.go b/pkg/extensions/extension_sync_disabled.go index 01d63be8..dbab182b 100644 --- a/pkg/extensions/extension_sync_disabled.go +++ b/pkg/extensions/extension_sync_disabled.go @@ -1,5 +1,4 @@ //go:build !sync -// +build !sync package extensions diff --git a/pkg/extensions/extension_ui.go b/pkg/extensions/extension_ui.go index 68988556..47e3a13a 100644 --- a/pkg/extensions/extension_ui.go +++ b/pkg/extensions/extension_ui.go @@ -1,5 +1,4 @@ //go:build search && ui -// +build search,ui package extensions diff --git a/pkg/extensions/extension_ui_disabled.go b/pkg/extensions/extension_ui_disabled.go index be5adc0d..515a01e6 100644 --- a/pkg/extensions/extension_ui_disabled.go +++ b/pkg/extensions/extension_ui_disabled.go @@ -1,5 +1,4 @@ //go:build !search || !ui -// +build !search !ui package extensions diff --git a/pkg/extensions/extension_ui_test.go b/pkg/extensions/extension_ui_test.go index 1735c243..eae793db 100644 --- a/pkg/extensions/extension_ui_test.go +++ b/pkg/extensions/extension_ui_test.go @@ -1,5 +1,4 @@ //go:build search && ui -// +build search,ui package extensions_test diff --git a/pkg/extensions/extension_userprefs.go b/pkg/extensions/extension_userprefs.go index bad09662..25612937 100644 --- a/pkg/extensions/extension_userprefs.go +++ b/pkg/extensions/extension_userprefs.go @@ -1,5 +1,4 @@ //go:build userprefs -// +build userprefs package extensions @@ -49,7 +48,7 @@ func SetupUserPreferencesRoutes(conf *config.Config, router *mux.Router, log.Info().Msg("finished setting up user preferences routes") } -// Repo preferences godoc +// HandleUserPrefs godoc // @Summary Add bookmarks/stars info // @Description Add bookmarks/stars info // @Router /v2/_zot/ext/userprefs [put] diff --git a/pkg/extensions/extension_userprefs_disable.go b/pkg/extensions/extension_userprefs_disable.go index f0845d61..54fe51b5 100644 --- a/pkg/extensions/extension_userprefs_disable.go +++ b/pkg/extensions/extension_userprefs_disable.go @@ -1,5 +1,4 @@ //go:build !userprefs -// +build !userprefs package extensions diff --git a/pkg/extensions/extension_userprefs_test.go b/pkg/extensions/extension_userprefs_test.go index 6db364fa..2696be75 100644 --- a/pkg/extensions/extension_userprefs_test.go +++ b/pkg/extensions/extension_userprefs_test.go @@ -1,5 +1,4 @@ //go:build userprefs -// +build userprefs package extensions_test diff --git a/pkg/extensions/extensions_lint.go b/pkg/extensions/extensions_lint.go index 1cd6da5f..21e65eef 100644 --- a/pkg/extensions/extensions_lint.go +++ b/pkg/extensions/extensions_lint.go @@ -1,5 +1,4 @@ //go:build lint -// +build lint package extensions diff --git a/pkg/extensions/extensions_lint_disabled.go b/pkg/extensions/extensions_lint_disabled.go index fb03180f..b7864772 100644 --- a/pkg/extensions/extensions_lint_disabled.go +++ b/pkg/extensions/extensions_lint_disabled.go @@ -1,5 +1,4 @@ //go:build !lint -// +build !lint package extensions diff --git a/pkg/extensions/extensions_test.go b/pkg/extensions/extensions_test.go index 9c798703..63289785 100644 --- a/pkg/extensions/extensions_test.go +++ b/pkg/extensions/extensions_test.go @@ -1,5 +1,4 @@ //go:build sync && metrics && mgmt && userprefs && search -// +build sync,metrics,mgmt,userprefs,search package extensions_test diff --git a/pkg/extensions/imagetrust/cosign.go b/pkg/extensions/imagetrust/cosign.go index cfc18535..6c3d7952 100644 --- a/pkg/extensions/imagetrust/cosign.go +++ b/pkg/extensions/imagetrust/cosign.go @@ -1,5 +1,4 @@ //go:build imagetrust -// +build imagetrust package imagetrust @@ -117,7 +116,6 @@ func VerifyCosignSignature( err = verifier.VerifySignature(bytes.NewReader(signature), bytes.NewReader(payload), options.WithContext(context.Background())) - if err == nil { return string(pubKeyContent), true, nil } diff --git a/pkg/extensions/imagetrust/image_trust.go b/pkg/extensions/imagetrust/image_trust.go index 03dd0f2f..69411f7d 100644 --- a/pkg/extensions/imagetrust/image_trust.go +++ b/pkg/extensions/imagetrust/image_trust.go @@ -1,5 +1,4 @@ //go:build imagetrust -// +build imagetrust package imagetrust @@ -92,7 +91,7 @@ func NewAWSImageTrustStore(region, endpoint string) (*ImageTrustStore, error) { func GetSecretsManagerClient(region, endpoint string) (*secretsmanager.Client, error) { customResolver := aws.EndpointResolverWithOptionsFunc( //nolint: staticcheck - func(service, region string, options ...interface{}) (aws.Endpoint, error) { //nolint: staticcheck + func(service, region string, options ...any) (aws.Endpoint, error) { //nolint: staticcheck return aws.Endpoint{ //nolint: staticcheck PartitionID: "aws", URL: endpoint, diff --git a/pkg/extensions/imagetrust/image_trust_disabled.go b/pkg/extensions/imagetrust/image_trust_disabled.go index 3e845b6b..f2e08618 100644 --- a/pkg/extensions/imagetrust/image_trust_disabled.go +++ b/pkg/extensions/imagetrust/image_trust_disabled.go @@ -1,5 +1,4 @@ //go:build !imagetrust -// +build !imagetrust package imagetrust diff --git a/pkg/extensions/imagetrust/image_trust_test.go b/pkg/extensions/imagetrust/image_trust_test.go index ce5c1491..af91afd3 100644 --- a/pkg/extensions/imagetrust/image_trust_test.go +++ b/pkg/extensions/imagetrust/image_trust_test.go @@ -1,5 +1,4 @@ //go:build imagetrust -// +build imagetrust package imagetrust_test @@ -648,7 +647,7 @@ func TestLocalTrustStore(t *testing.T) { imageTrustStore, err := imagetrust.NewLocalImageTrustStore(rootDir) So(err, ShouldBeNil) - var dbDriverParams map[string]interface{} + var dbDriverParams map[string]any RunUploadTests(t, *imageTrustStore) RunVerificationTests(t, dbDriverParams) @@ -664,7 +663,7 @@ func TestLocalTrustStoreRedis(t *testing.T) { imageTrustStore, err := imagetrust.NewLocalImageTrustStore(rootDir) So(err, ShouldBeNil) - dbDriverParams := map[string]interface{}{ + dbDriverParams := map[string]any{ "name": "redis", "url": "redis://" + miniRedis.Addr(), } @@ -1094,7 +1093,7 @@ func TestAWSTrustStore(t *testing.T) { imageMetaTablename := "imageMetaTable" + uuid.String() repoBlobsInfoTablename := "repoBlobsInfoTable" + uuid.String() - dynamoDBDriverParams := map[string]interface{}{ + dynamoDBDriverParams := map[string]any{ "name": "dynamodb", "endpoint": os.Getenv("DYNAMODBMOCK_ENDPOINT"), "region": "us-east-2", @@ -1205,7 +1204,7 @@ func RunUploadTests(t *testing.T, imageTrustStore imagetrust.ImageTrustStore) { }) } -func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) { //nolint: thelper +func RunVerificationTests(t *testing.T, dbDriverParams map[string]any) { //nolint: thelper Convey("verify signatures are trusted", func() { defaultValue := true rootDir := t.TempDir() diff --git a/pkg/extensions/imagetrust/notation.go b/pkg/extensions/imagetrust/notation.go index 4959849b..c7bc2ccb 100644 --- a/pkg/extensions/imagetrust/notation.go +++ b/pkg/extensions/imagetrust/notation.go @@ -1,5 +1,4 @@ //go:build imagetrust -// +build imagetrust package imagetrust @@ -211,7 +210,7 @@ func (cloud *CertificateAWSStorage) recreateSecret(secretInputParam *secretsmana var err error - for i := 0; i < maxAttempts; i++ { + for range maxAttempts { _, err = cloud.secretsManagerClient.CreateSecret(context.Background(), secretInputParam) if err == nil { return nil @@ -286,7 +285,8 @@ func (cloud *CertificateAWSStorage) GetCertificates( return certificates, nil } -// Equivalent function for trustpolicy.LoadDocument() but using a specific SysFS not the one returned by ConfigFS(). +// LoadTrustPolicyDocument is equivalent to trustpolicy.LoadDocument() but using a specific SysFS +// not the one returned by ConfigFS(). func (local *CertificateLocalStorage) LoadTrustPolicyDocument() (*trustpolicy.Document, error) { notationDir, err := local.GetNotationDirPath() if err != nil { diff --git a/pkg/extensions/lint/lint.go b/pkg/extensions/lint/lint.go index 1be3bafd..1902f922 100644 --- a/pkg/extensions/lint/lint.go +++ b/pkg/extensions/lint/lint.go @@ -1,5 +1,4 @@ //go:build lint -// +build lint package lint diff --git a/pkg/extensions/lint/lint_disabled.go b/pkg/extensions/lint/lint_disabled.go index 11095777..9f9dd1f7 100644 --- a/pkg/extensions/lint/lint_disabled.go +++ b/pkg/extensions/lint/lint_disabled.go @@ -1,5 +1,4 @@ //go:build !lint -// +build !lint package lint diff --git a/pkg/extensions/lint/lint_test.go b/pkg/extensions/lint/lint_test.go index d1e4a69f..40a9a66e 100644 --- a/pkg/extensions/lint/lint_test.go +++ b/pkg/extensions/lint/lint_test.go @@ -1,5 +1,4 @@ //go:build lint -// +build lint package lint_test diff --git a/pkg/extensions/monitoring/common.go b/pkg/extensions/monitoring/common.go index e9be85d4..0390b160 100644 --- a/pkg/extensions/monitoring/common.go +++ b/pkg/extensions/monitoring/common.go @@ -9,10 +9,10 @@ import ( var re = regexp.MustCompile(`\/v2\/(.*?)\/(blobs|tags|manifests)\/(.*)$`) type MetricServer interface { - SendMetric(interface{}) + SendMetric(any) // works like SendMetric, but adds the metric regardless of the value of 'enabled' field for MetricServer - ForceSendMetric(interface{}) - ReceiveMetrics() interface{} + ForceSendMetric(any) + ReceiveMetrics() any IsEnabled() bool // Stop gracefully shuts down the metrics server Stop() diff --git a/pkg/extensions/monitoring/extension.go b/pkg/extensions/monitoring/extension.go index d9a9b66f..5360243f 100644 --- a/pkg/extensions/monitoring/extension.go +++ b/pkg/extensions/monitoring/extension.go @@ -1,5 +1,4 @@ //go:build metrics -// +build metrics package monitoring @@ -157,8 +156,8 @@ func NewMetricsServer(enabled bool, log log.Logger) MetricServer { } } -// implementing the MetricServer interface. -func (ms *metricServer) SendMetric(mfunc interface{}) { +// SendMetric implements the MetricServer interface. +func (ms *metricServer) SendMetric(mfunc any) { if ms.enabled { mfn, ok := mfunc.(func()) if !ok { @@ -172,7 +171,7 @@ func (ms *metricServer) SendMetric(mfunc interface{}) { } } -func (ms *metricServer) ForceSendMetric(mfunc interface{}) { +func (ms *metricServer) ForceSendMetric(mfunc any) { mfn, ok := mfunc.(func()) if !ok { ms.log.Error().Err(errors.ErrInvalidMetric). @@ -184,7 +183,7 @@ func (ms *metricServer) ForceSendMetric(mfunc interface{}) { mfn() } -func (ms *metricServer) ReceiveMetrics() interface{} { +func (ms *metricServer) ReceiveMetrics() any { return nil } diff --git a/pkg/extensions/monitoring/minimal.go b/pkg/extensions/monitoring/minimal.go index 5b8b2ec2..882d32f4 100644 --- a/pkg/extensions/monitoring/minimal.go +++ b/pkg/extensions/monitoring/minimal.go @@ -1,5 +1,4 @@ //go:build !metrics -// +build !metrics //nolint:varnamelen,forcetypeassert package monitoring @@ -43,7 +42,7 @@ const ( type metricServer struct { enabled bool lastCheck time.Time - reqChan chan interface{} + reqChan chan any cache *MetricsInfo cacheChan chan MetricsCopy bucketsF2S map[float64]string // float64 to string conversion of buckets label @@ -110,8 +109,8 @@ func GetStorageLatencyBuckets() []float64 { return []float64{.001, .01, 0.1, 1, 5, 10, 15, 30, 60, math.MaxFloat64} } -// implements the MetricServer interface. -func (ms *metricServer) SendMetric(metric interface{}) { +// SendMetric implements the MetricServer interface. +func (ms *metricServer) SendMetric(metric any) { ms.lock.RLock() if ms.enabled { ms.lock.RUnlock() @@ -121,11 +120,11 @@ func (ms *metricServer) SendMetric(metric interface{}) { } } -func (ms *metricServer) ForceSendMetric(metric interface{}) { +func (ms *metricServer) ForceSendMetric(metric any) { ms.reqChan <- metric } -func (ms *metricServer) ReceiveMetrics() interface{} { +func (ms *metricServer) ReceiveMetrics() any { ms.lock.Lock() if !ms.enabled { ms.enabled = true @@ -250,7 +249,7 @@ func NewMetricsServer(enabled bool, log log.Logger) MetricServer { ms := &metricServer{ enabled: enabled, - reqChan: make(chan interface{}), + reqChan: make(chan any), cacheChan: make(chan MetricsCopy), cache: mi, bucketsF2S: bucketsFloat2String, @@ -264,7 +263,7 @@ func NewMetricsServer(enabled bool, log log.Logger) MetricServer { return ms } -// contains a map with key=CounterName and value=CounterLabels. +// GetCounters contains a map with key=CounterName and value=CounterLabels. func GetCounters() map[string][]string { return map[string][]string{ httpConnRequests: {"method", "code"}, diff --git a/pkg/extensions/monitoring/minimal_client.go b/pkg/extensions/monitoring/minimal_client.go index c5d876e9..6edf39c1 100644 --- a/pkg/extensions/monitoring/minimal_client.go +++ b/pkg/extensions/monitoring/minimal_client.go @@ -1,5 +1,4 @@ //go:build !metrics -// +build !metrics package monitoring @@ -47,8 +46,8 @@ func newHTTPMetricsClient() *http.Client { } } -// Creates a MetricsClient that can be used to retrieve in memory metrics -// The new MetricsClient retrieved must be cached and reused by the Node Exporter +// NewMetricsClient creates a MetricsClient that can be used to retrieve in memory metrics. +// The new MetricsClient retrieved must be cached and reused by the Node Exporter // in order to prevent concurrent memory leaks. func NewMetricsClient(config *MetricsConfig, logger log.Logger) *MetricsClient { if config.HTTPClient == nil { @@ -67,7 +66,7 @@ func (mc *MetricsClient) GetMetrics() (*MetricsInfo, error) { return metrics, nil } -func (mc *MetricsClient) makeGETRequest(url string, resultsPtr interface{}) (http.Header, error) { +func (mc *MetricsClient) makeGETRequest(url string, resultsPtr any) (http.Header, error) { req, err := http.NewRequestWithContext(context.Background(), http.MethodGet, url, nil) if err != nil { return nil, fmt.Errorf("metric scraping failed: %w", err) diff --git a/pkg/extensions/monitoring/monitoring_test.go b/pkg/extensions/monitoring/monitoring_test.go index 3bddfc86..4eb34edc 100644 --- a/pkg/extensions/monitoring/monitoring_test.go +++ b/pkg/extensions/monitoring/monitoring_test.go @@ -1,5 +1,4 @@ //go:build metrics -// +build metrics package monitoring_test diff --git a/pkg/extensions/scrub/scrub.go b/pkg/extensions/scrub/scrub.go index 7a53f340..81753e5a 100644 --- a/pkg/extensions/scrub/scrub.go +++ b/pkg/extensions/scrub/scrub.go @@ -1,5 +1,4 @@ //go:build scrub -// +build scrub package scrub @@ -13,7 +12,7 @@ import ( storageTypes "zotregistry.dev/zot/v2/pkg/storage/types" ) -// Scrub Extension for repo... +// RunScrubRepo runs the scrub extension for a repository. func RunScrubRepo(ctx context.Context, imgStore storageTypes.ImageStore, repo string, log log.Logger) error { execMsg := "executing scrub to check manifest/blob integrity for " + path.Join(imgStore.RootDir(), repo) log.Info().Msg(execMsg) diff --git a/pkg/extensions/scrub/scrub_test.go b/pkg/extensions/scrub/scrub_test.go index fc299424..86b15ebb 100644 --- a/pkg/extensions/scrub/scrub_test.go +++ b/pkg/extensions/scrub/scrub_test.go @@ -1,5 +1,4 @@ //go:build scrub -// +build scrub package scrub_test diff --git a/pkg/extensions/search/convert/annotations.go b/pkg/extensions/search/convert/annotations.go index 66f3eb0b..e0138356 100644 --- a/pkg/extensions/search/convert/annotations.go +++ b/pkg/extensions/search/convert/annotations.go @@ -7,6 +7,7 @@ import ( ) const ( + // AnnotationLabels is used for OCI annotation/label with backwards compatibility. // See https://github.com/opencontainers/image-spec/blob/main/annotations.md#back-compatibility-with-label-schema AnnotationLabels = "org.label-schema.labels" LabelAnnotationCreated = "org.label-schema.build-date" @@ -30,12 +31,9 @@ type ImageAnnotations struct { Authors string } -/* - OCI annotation/label with backwards compatibility - -arg can be either labels or annotations -https://github.com/opencontainers/image-spec/blob/main/annotations.md. -*/ +// GetAnnotationValue handles OCI annotation/label with backwards compatibility. +// Arg can be either labels or annotations. +// https://github.com/opencontainers/image-spec/blob/main/annotations.md. func GetAnnotationValue(annotations map[string]string, annotationKey, labelKey string) string { value, ok := annotations[annotationKey] if !ok || value == "" { diff --git a/pkg/extensions/search/convert/metadb.go b/pkg/extensions/search/convert/metadb.go index f2de6f85..d3c0af2c 100644 --- a/pkg/extensions/search/convert/metadb.go +++ b/pkg/extensions/search/convert/metadb.go @@ -45,8 +45,6 @@ func getReferrers(referrersInfo []mTypes.ReferrerInfo) []*gql_generated.Referrer referrers := make([]*gql_generated.Referrer, 0, len(referrersInfo)) for _, referrerInfo := range referrersInfo { - referrerInfo := referrerInfo - referrers = append(referrers, &gql_generated.Referrer{ MediaType: &referrerInfo.MediaType, ArtifactType: &referrerInfo.ArtifactType, @@ -63,9 +61,6 @@ func getAnnotationsFromMap(annotationsMap map[string]string) []*gql_generated.An annotations := make([]*gql_generated.Annotation, 0, len(annotationsMap)) for key, value := range annotationsMap { - key := key - value := value - annotations = append(annotations, &gql_generated.Annotation{ Key: &key, Value: &value, @@ -199,9 +194,6 @@ func StringMap2Annotations(strMap map[string]string) []*gql_generated.Annotation annotations := make([]*gql_generated.Annotation, 0, len(strMap)) for key, value := range strMap { - key := key - value := value - annotations = append(annotations, &gql_generated.Annotation{ Key: &key, Value: &value, diff --git a/pkg/extensions/search/convert/utils.go b/pkg/extensions/search/convert/utils.go index 662c8acc..a2440d89 100644 --- a/pkg/extensions/search/convert/utils.go +++ b/pkg/extensions/search/convert/utils.go @@ -1,19 +1,30 @@ package convert import ( + "slices" + zcommon "zotregistry.dev/zot/v2/pkg/common" gql_gen "zotregistry.dev/zot/v2/pkg/extensions/search/gql_generated" mTypes "zotregistry.dev/zot/v2/pkg/meta/types" ) func ImgSumAcceptedByFilter(imageSummary *gql_gen.ImageSummary, filter mTypes.Filter) bool { - osFilters := strSliceFromRef(filter.Os) - archFilters := strSliceFromRef(filter.Arch) + // Early return if image is not signed and signing is required + if filter.HasToBeSigned != nil && *filter.HasToBeSigned && !*imageSummary.IsSigned { + return false + } + platforms := getImagePlatforms(imageSummary) - platformMatchFound := len(platforms) == 0 && filter.Os == nil && filter.Arch == nil + // Early return if no platforms and no filters means platform match passes + if len(platforms) == 0 && filter.Os == nil && filter.Arch == nil { + return true + } - for _, platform := range platforms { + osFilters := strSliceFromRef(filter.Os) + archFilters := strSliceFromRef(filter.Arch) + + return slices.ContainsFunc(platforms, func(platform *gql_gen.Platform) bool { osCheck := true if len(osFilters) > 0 { @@ -26,26 +37,12 @@ func ImgSumAcceptedByFilter(imageSummary *gql_gen.ImageSummary, filter mTypes.Fi archCheck = platform.Arch != nil && zcommon.ContainsStringIgnoreCase(archFilters, *platform.Arch) } - if osCheck && archCheck { - platformMatchFound = true - - break - } - } - - if !platformMatchFound { - return false - } - - if filter.HasToBeSigned != nil && *filter.HasToBeSigned && !*imageSummary.IsSigned { - return false - } - - return true + return osCheck && archCheck + }) } func getImagePlatforms(imageSummary *gql_gen.ImageSummary) []*gql_gen.Platform { - platforms := []*gql_gen.Platform{} + platforms := make([]*gql_gen.Platform, 0, len(imageSummary.Manifests)) for _, manifest := range imageSummary.Manifests { if manifest.Platform != nil { @@ -57,35 +54,6 @@ func getImagePlatforms(imageSummary *gql_gen.ImageSummary) []*gql_gen.Platform { } func RepoSumAcceptedByFilter(repoSummary *gql_gen.RepoSummary, filter mTypes.Filter) bool { - osFilters := strSliceFromRef(filter.Os) - archFilters := strSliceFromRef(filter.Arch) - - platformMatchFound := len(repoSummary.Platforms) == 0 && filter.Os == nil && filter.Arch == nil - - for _, platform := range repoSummary.Platforms { - osCheck := true - - if len(osFilters) > 0 { - osCheck = platform.Os != nil && zcommon.ContainsStringIgnoreCase(osFilters, *platform.Os) - } - - archCheck := true - - if len(archFilters) > 0 { - archCheck = platform.Arch != nil && zcommon.ContainsStringIgnoreCase(archFilters, *platform.Arch) - } - - if osCheck && archCheck { - platformMatchFound = true - - break - } - } - - if !platformMatchFound { - return false - } - if filter.HasToBeSigned != nil && *filter.HasToBeSigned && !*repoSummary.NewestImage.IsSigned { return false } @@ -98,7 +66,29 @@ func RepoSumAcceptedByFilter(repoSummary *gql_gen.RepoSummary, filter mTypes.Fil return false } - return true + // Early return if no platforms and no filters means platform match passes + if len(repoSummary.Platforms) == 0 && filter.Os == nil && filter.Arch == nil { + return true + } + + osFilters := strSliceFromRef(filter.Os) + archFilters := strSliceFromRef(filter.Arch) + + return slices.ContainsFunc(repoSummary.Platforms, func(platform *gql_gen.Platform) bool { + osCheck := true + + if len(osFilters) > 0 { + osCheck = platform.Os != nil && zcommon.ContainsStringIgnoreCase(osFilters, *platform.Os) + } + + archCheck := true + + if len(archFilters) > 0 { + archCheck = platform.Arch != nil && zcommon.ContainsStringIgnoreCase(archFilters, *platform.Arch) + } + + return osCheck && archCheck + }) } func strSliceFromRef(slice []*string) []string { diff --git a/pkg/extensions/search/cve/cve.go b/pkg/extensions/search/cve/cve.go index 729338d5..7231dca7 100644 --- a/pkg/extensions/search/cve/cve.go +++ b/pkg/extensions/search/cve/cve.go @@ -436,7 +436,6 @@ func (cveinfo BaseCveInfo) GetCVEDiffListForImages(ctx context.Context, minuend, subtrahendCVEMap := map[string]cvemodel.CVE{} for _, cve := range subtrahendCVEList { - cve := cve subtrahendCVEMap[cve.ID] = cve } diff --git a/pkg/extensions/search/cve/cve_test.go b/pkg/extensions/search/cve/cve_test.go index f3d789e9..8e950811 100644 --- a/pkg/extensions/search/cve/cve_test.go +++ b/pkg/extensions/search/cve/cve_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search //nolint:lll,gosimple package cveinfo_test @@ -12,6 +11,7 @@ import ( "net/url" "os" "path" + "slices" "strings" "testing" "time" @@ -969,7 +969,7 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo return result, nil } - if repo == repo1 && zcommon.Contains([]string{image12Digest, image21Digest}, ref) { + if repo == repo1 && slices.Contains([]string{image12Digest, image21Digest}, ref) { result := map[string]cvemodel.CVE{ "CVE1": { ID: "CVE1", @@ -1158,10 +1158,8 @@ func TestCVEStruct(t *testing.T) { //nolint:gocyclo for _, imageLayer := range manifestData.Manifests[0].Manifest.Layers { switch imageLayer.MediaType { case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer): - return true, nil default: - return false, zerr.ErrScanNotSupported } } diff --git a/pkg/extensions/search/cve/pagination_test.go b/pkg/extensions/search/cve/pagination_test.go index 6c612334..a83e5774 100644 --- a/pkg/extensions/search/cve/pagination_test.go +++ b/pkg/extensions/search/cve/pagination_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package cveinfo_test @@ -77,7 +76,7 @@ func TestCVEPagination(t *testing.T) { cveMap := map[string]cvemodel.CVE{} if image == "repo1:0.1.0" { - for i := 0; i < 5; i++ { + for i := range 5 { cveMap[fmt.Sprintf("CVE%d", i)] = cvemodel.CVE{ ID: fmt.Sprintf("CVE%d", i), Severity: intToSeverity[i%5], @@ -88,7 +87,7 @@ func TestCVEPagination(t *testing.T) { } if image == "repo1:1.0.0" { - for i := 0; i < 30; i++ { + for i := range 30 { cveMap[fmt.Sprintf("CVE%d", i)] = cvemodel.CVE{ ID: fmt.Sprintf("CVE%d", i), Severity: intToSeverity[i%5], @@ -183,7 +182,7 @@ func TestCVEPagination(t *testing.T) { Convey("no limit or offset", func() { cveIds := []string{} - for i := 0; i < 30; i++ { + for i := range 30 { cveIds = append(cveIds, fmt.Sprintf("CVE%d", i)) } @@ -266,7 +265,7 @@ func TestCVEPagination(t *testing.T) { Convey("limit < len(cves)", func() { cveIds := []string{} - for i := 0; i < 30; i++ { + for i := range 30 { cveIds = append(cveIds, fmt.Sprintf("CVE%d", i)) } diff --git a/pkg/extensions/search/cve/scan_test.go b/pkg/extensions/search/cve/scan_test.go index dd6db8d3..f1df966c 100644 --- a/pkg/extensions/search/cve/scan_test.go +++ b/pkg/extensions/search/cve/scan_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package cveinfo_test @@ -8,6 +7,7 @@ import ( "errors" "io" "os" + "slices" "testing" "time" @@ -249,7 +249,7 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo return result, nil } - if repo == repo1 && zcommon.Contains([]string{image12Digest, image21Digest}, ref) { + if repo == repo1 && slices.Contains([]string{image12Digest, image21Digest}, ref) { result := map[string]cvemodel.CVE{ "CVE1": { ID: "CVE1", @@ -392,10 +392,8 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo for _, imageLayer := range manifestData.Manifests[0].Manifest.Layers { switch imageLayer.MediaType { case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer): - return true, nil default: - return false, zerr.ErrScanNotSupported } } diff --git a/pkg/extensions/search/cve/trivy/scanner.go b/pkg/extensions/search/cve/trivy/scanner.go index fd368f82..f850d3f6 100644 --- a/pkg/extensions/search/cve/trivy/scanner.go +++ b/pkg/extensions/search/cve/trivy/scanner.go @@ -3,6 +3,7 @@ package trivy import ( "context" "fmt" + "maps" "os" "path" "strconv" @@ -537,9 +538,7 @@ func (scanner Scanner) scanIndex(ctx context.Context, repo, digest string) (map[ return nil, err } - for vulnerabilityID, CVE := range manifestCveIDMap { - indexCveIDMap[vulnerabilityID] = CVE - } + maps.Copy(indexCveIDMap, manifestCveIDMap) } } diff --git a/pkg/extensions/search/cve/trivy/scanner_internal_test.go b/pkg/extensions/search/cve/trivy/scanner_internal_test.go index 8ab0be7c..c9f7f1df 100644 --- a/pkg/extensions/search/cve/trivy/scanner_internal_test.go +++ b/pkg/extensions/search/cve/trivy/scanner_internal_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package trivy diff --git a/pkg/extensions/search/cve/update_test.go b/pkg/extensions/search/cve/update_test.go index 0a3f0b34..cbe5ceb8 100644 --- a/pkg/extensions/search/cve/update_test.go +++ b/pkg/extensions/search/cve/update_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package cveinfo_test diff --git a/pkg/extensions/search/digest_test.go b/pkg/extensions/search/digest_test.go index a1e2d705..af49ba62 100644 --- a/pkg/extensions/search/digest_test.go +++ b/pkg/extensions/search/digest_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package search_test diff --git a/pkg/extensions/search/pagination/image_pagination.go b/pkg/extensions/search/pagination/image_pagination.go index 2989cf18..e1febf39 100644 --- a/pkg/extensions/search/pagination/image_pagination.go +++ b/pkg/extensions/search/pagination/image_pagination.go @@ -136,7 +136,7 @@ func ImgSortByRelevance(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool } } -// SortByUpdateTime sorting descending by time. +// ImgSortByUpdateTime sorts descending by time. func ImgSortByUpdateTime(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool { repos2LastUpdated := map[string]time.Time{} @@ -156,7 +156,7 @@ func ImgSortByUpdateTime(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool } } -// SortByDownloads returns a comparison function for descendant sorting by downloads. +// ImgSortByDownloads returns a comparison function for descendant sorting by downloads. func ImgSortByDownloads(pageBuffer []*gql_gen.ImageSummary) func(i, j int) bool { return func(i, j int) bool { return *pageBuffer[i].DownloadCount > *pageBuffer[j].DownloadCount diff --git a/pkg/extensions/search/pagination/repo_pagination.go b/pkg/extensions/search/pagination/repo_pagination.go index 209b1057..991ba5d8 100644 --- a/pkg/extensions/search/pagination/repo_pagination.go +++ b/pkg/extensions/search/pagination/repo_pagination.go @@ -111,14 +111,14 @@ func RepoSortByRelevance(pageBuffer []*gql_gen.RepoSummary) func(i, j int) bool } } -// SortByUpdateTime sorting descending by time. +// RepoSortByUpdateTime sorts descending by time. func RepoSortByUpdateTime(pageBuffer []*gql_gen.RepoSummary) func(i, j int) bool { return func(i, j int) bool { return pageBuffer[i].LastUpdated.After(*pageBuffer[j].LastUpdated) } } -// SortByDownloads returns a comparison function for descendant sorting by downloads. +// RepoSortByDownloads returns a comparison function for descendant sorting by downloads. func RepoSortByDownloads(pageBuffer []*gql_gen.RepoSummary) func(i, j int) bool { return func(i, j int) bool { return *pageBuffer[i].DownloadCount > *pageBuffer[j].DownloadCount diff --git a/pkg/extensions/search/resolver.go b/pkg/extensions/search/resolver.go index a82c48e6..22f077bf 100644 --- a/pkg/extensions/search/resolver.go +++ b/pkg/extensions/search/resolver.go @@ -8,6 +8,7 @@ import ( "context" "errors" "fmt" + "slices" "sort" "strings" @@ -236,8 +237,6 @@ func getCVEListForImage( pkgList := make([]*gql_generated.PackageInfo, 0) for _, pkg := range cveDetail.PackageList { - pkg := pkg - pkgList = append(pkgList, &gql_generated.PackageInfo{ Name: &pkg.Name, @@ -386,8 +385,6 @@ func getCVEDiffListForImages( pkgList := make([]*gql_generated.PackageInfo, 0) for _, pkg := range cveDetail.PackageList { - pkg := pkg - pkgList = append(pkgList, &gql_generated.PackageInfo{ Name: &pkg.Name, @@ -805,7 +802,7 @@ func getBookmarkedRepos( } filterByName := func(repo string) bool { - return zcommon.Contains(bookmarkedRepos, repo) + return slices.Contains(bookmarkedRepos, repo) } return getFilteredPaginatedRepos(ctx, cveInfo, filterByName, log, requestedPage, metaDB) @@ -824,7 +821,7 @@ func getStarredRepos( } filterFn := func(repo string) bool { - return zcommon.Contains(starredRepos, repo) + return slices.Contains(starredRepos, repo) } return getFilteredPaginatedRepos(ctx, cveInfo, filterFn, log, requestedPage, metaDB) @@ -1445,7 +1442,7 @@ func expandedRepoInfo(ctx context.Context, repo string, metaDB mTypes.MetaDB, cv digest := repoMeta.Tags[i].Digest - if !zcommon.Contains(tagsDigests, digest) { + if !slices.Contains(tagsDigests, digest) { tagsDigests = append(tagsDigests, digest) } } @@ -1582,8 +1579,6 @@ func getReferrers(metaDB mTypes.MetaDB, repo string, referredDigest string, arti results := make([]*gql_generated.Referrer, 0, len(referrers)) for _, referrer := range referrers { - referrer := referrer - results = append(results, &gql_generated.Referrer{ MediaType: &referrer.MediaType, ArtifactType: &referrer.ArtifactType, diff --git a/pkg/extensions/search/search_test.go b/pkg/extensions/search/search_test.go index 4879abe3..d3742bad 100644 --- a/pkg/extensions/search/search_test.go +++ b/pkg/extensions/search/search_test.go @@ -1,5 +1,4 @@ //go:build search -// +build search package search_test @@ -340,10 +339,8 @@ func getMockCveScanner(metaDB mTypes.MetaDB) cveinfo.Scanner { for _, imageLayer := range manifestData.Manifests[0].Manifest.Layers { switch imageLayer.MediaType { case ispec.MediaTypeImageLayerGzip, ispec.MediaTypeImageLayer, string(regTypes.DockerLayer): - return true, nil default: - return false, zerr.ErrScanNotSupported } } @@ -3496,8 +3493,6 @@ func TestGlobalSearch(t *testing.T) { //nolint: gocyclo So(newestImageMap["repo2"].LastUpdated, ShouldEqual, time.Date(2009, 2, 1, 12, 0, 0, 0, time.UTC)) for repoName, repoSummary := range actualRepoMap { - repoSummary := repoSummary - // Check if data in NewestImage is consistent with the data in RepoSummary So(repoName, ShouldEqual, repoSummary.NewestImage.RepoName) So(repoSummary.Name, ShouldEqual, repoSummary.NewestImage.RepoName) @@ -3841,8 +3836,6 @@ func TestGlobalSearch(t *testing.T) { //nolint: gocyclo So(newestImageMap["repo2"].LastUpdated, ShouldEqual, time.Date(2009, 2, 1, 12, 0, 0, 0, time.UTC)) for repoName, repoSummary := range actualRepoMap { - repoSummary := repoSummary - // Check if data in NewestImage is consistent with the data in RepoSummary So(repoName, ShouldEqual, repoSummary.NewestImage.RepoName) So(repoSummary.Name, ShouldEqual, repoSummary.NewestImage.RepoName) @@ -4174,7 +4167,7 @@ func TestGlobalSearch(t *testing.T) { //nolint: gocyclo Convey("test with redis", func() { miniRedis := miniredis.RunT(t) - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "redis", "url": "redis://" + miniRedis.Addr(), } @@ -4337,7 +4330,7 @@ func TestGlobalSearch(t *testing.T) { //nolint: gocyclo Convey("test with redis", func() { miniRedis := miniredis.RunT(t) - conf.Storage.CacheDriver = map[string]interface{}{ + conf.Storage.CacheDriver = map[string]any{ "name": "redis", "url": "redis://" + miniRedis.Addr(), } @@ -4900,7 +4893,7 @@ func TestGlobalSearchPagination(t *testing.T) { ctlrManager.StartAndWait(port) defer ctlrManager.StopServer() - for i := 0; i < 3; i++ { + for i := range 3 { image := CreateImageWith().RandomLayers(1, 10).DefaultConfig().Build() err := UploadImage(image, baseURL, fmt.Sprintf("repo%d", i), "0.0.1") @@ -7432,7 +7425,7 @@ func TestReadUploadDeleteDynamoDB(t *testing.T) { imageMetaTablename := "ImageMeta" + uuid.String() repoBlobsTablename := "RepoBlobs" + uuid.String() - cacheDriverParams := map[string]interface{}{ + cacheDriverParams := map[string]any{ "name": "dynamodb", "endpoint": os.Getenv("DYNAMODBMOCK_ENDPOINT"), "region": "us-east-2", @@ -7557,7 +7550,7 @@ func RunReadUploadDeleteTests(t *testing.T, baseURL string) { }) }) Convey("Delete the image pushed multiple times", func() { - for i := 0; i < 3; i++ { + for range 3 { status, err := DeleteImage(repo1, tag1, baseURL) So(status, ShouldBeIn, []int{http.StatusAccepted, http.StatusNotFound, http.StatusBadRequest}) So(err, ShouldBeNil) @@ -7567,7 +7560,7 @@ func RunReadUploadDeleteTests(t *testing.T, baseURL string) { } }) Convey("Upload same image multiple times", func() { - for i := 0; i < 3; i++ { + for range 3 { err := UploadImage(image, baseURL, repo1, tag1) So(err, ShouldBeNil) } diff --git a/pkg/extensions/sync/content.go b/pkg/extensions/sync/content.go index 4ba4c318..60947691 100644 --- a/pkg/extensions/sync/content.go +++ b/pkg/extensions/sync/content.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync diff --git a/pkg/extensions/sync/content_test.go b/pkg/extensions/sync/content_test.go index b231b3f3..5e1ad186 100644 --- a/pkg/extensions/sync/content_test.go +++ b/pkg/extensions/sync/content_test.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync_test //nolint: testpackage diff --git a/pkg/extensions/sync/destination.go b/pkg/extensions/sync/destination.go index be13ed83..69c73d2f 100644 --- a/pkg/extensions/sync/destination.go +++ b/pkg/extensions/sync/destination.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync @@ -10,6 +9,7 @@ import ( "fmt" "os" "path" + "slices" "strings" "github.com/distribution/distribution/v3/registry/storage/driver" @@ -53,7 +53,7 @@ func NewDestinationRegistry( } } -// Check if image is already synced. +// CanSkipImage checks if image is already synced. func (registry *DestinationRegistry) CanSkipImage(repo, tag string, digest godigest.Digest) (bool, error) { // check image already synced imageStore := registry.storeController.GetImageStore(repo) @@ -86,7 +86,7 @@ func (registry *DestinationRegistry) GetImageReference(repo, reference string) ( return registry.tempStorage.GetImageReference(repo, reference) } -// finalize a syncing image. +// CommitAll finalizes a syncing image. func (registry *DestinationRegistry) CommitAll(repo string, imageReference ref.Ref) error { tempImageStore := getImageStoreFromImageReference(repo, imageReference, registry.log) @@ -145,7 +145,7 @@ func (registry *DestinationRegistry) copyManifest(repo string, desc ispec.Descri var err error // seen - if common.Contains(*seen, desc.Digest) { + if slices.Contains(*seen, desc.Digest) { return nil } diff --git a/pkg/extensions/sync/ecr_credential_helper.go b/pkg/extensions/sync/ecr_credential_helper.go index 5e5395e9..7c085fb0 100644 --- a/pkg/extensions/sync/ecr_credential_helper.go +++ b/pkg/extensions/sync/ecr_credential_helper.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync @@ -73,7 +72,7 @@ func extractAccountAndRegion(url string) (string, string, error) { return accountID, region, nil } -// getMockECRCredentials provides mock credentials for testing purposes. +// GetMockECRCredentials provides mock credentials for testing purposes. func GetMockECRCredentials(remoteAddress string) (ecrCredential, error) { // Extract account ID and region from the URL. accountID, region, err := extractAccountAndRegion(remoteAddress) @@ -91,7 +90,7 @@ func GetMockECRCredentials(remoteAddress string) (ecrCredential, error) { }, nil } -// getECRCredentials retrieves actual ECR credentials using AWS SDK. +// GetECRCredentials retrieves actual ECR credentials using AWS SDK. func GetECRCredentials(remoteAddress string) (ecrCredential, error) { // Extract account ID and region from the URL. accountID, region, err := extractAccountAndRegion(remoteAddress) @@ -137,7 +136,7 @@ func GetECRCredentials(remoteAddress string) (ecrCredential, error) { return ecrCredential{username: username, password: password, expiry: expiry, account: accountID, region: region}, nil } -// GetECRCredentials retrieves the ECR credentials (username and password) from AWS ECR. +// GetCredentials retrieves the ECR credentials (username and password) from AWS ECR. func (credHelper *ecrCredentialsHelper) GetCredentials(urls []string) (syncconf.CredentialsFile, error) { ecrCredentials := make(syncconf.CredentialsFile) diff --git a/pkg/extensions/sync/oci_layout.go b/pkg/extensions/sync/oci_layout.go index 50f5ef37..9e018dc0 100644 --- a/pkg/extensions/sync/oci_layout.go +++ b/pkg/extensions/sync/oci_layout.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync diff --git a/pkg/extensions/sync/on_demand.go b/pkg/extensions/sync/on_demand.go index f408a46b..443cb1fb 100644 --- a/pkg/extensions/sync/on_demand.go +++ b/pkg/extensions/sync/on_demand.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync @@ -23,9 +22,9 @@ type request struct { } /* - a request can be an image/signature/sbom +BaseOnDemand tracks requests that can be an image/signature/sbom. -keep track of all parallel requests, if two requests of same image/signature/sbom comes at the same time, +It keeps track of all parallel requests, if two requests of same image/signature/sbom comes at the same time, process just the first one, also keep track of all background retrying routines. */ type BaseOnDemand struct { diff --git a/pkg/extensions/sync/on_demand_disabled.go b/pkg/extensions/sync/on_demand_disabled.go index 08c891d2..54c2ed36 100644 --- a/pkg/extensions/sync/on_demand_disabled.go +++ b/pkg/extensions/sync/on_demand_disabled.go @@ -1,5 +1,4 @@ //go:build !sync -// +build !sync package sync diff --git a/pkg/extensions/sync/referrers.go b/pkg/extensions/sync/referrers.go index 8c6a5234..be88d038 100644 --- a/pkg/extensions/sync/referrers.go +++ b/pkg/extensions/sync/referrers.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync diff --git a/pkg/extensions/sync/remote.go b/pkg/extensions/sync/remote.go index 17f7aa6c..9e35bac4 100644 --- a/pkg/extensions/sync/remote.go +++ b/pkg/extensions/sync/remote.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync @@ -195,7 +194,7 @@ func (registry *RemoteRegistry) GetDigest(ctx context.Context, repo, tag string, return man.GetDescriptor().Digest, err } -// returns OCI remote digest, original remote digest (unconverted), if it was converted. +// GetOCIDigest returns OCI remote digest, original remote digest (unconverted), if it was converted. func (registry *RemoteRegistry) GetOCIDigest(ctx context.Context, repo, tag string, ) (godigest.Digest, godigest.Digest, bool, error) { var isConverted bool diff --git a/pkg/extensions/sync/repo_tags_cache.go b/pkg/extensions/sync/repo_tags_cache.go index 689a5063..fef98dd2 100644 --- a/pkg/extensions/sync/repo_tags_cache.go +++ b/pkg/extensions/sync/repo_tags_cache.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync @@ -27,7 +26,7 @@ func newTagsCache(expireAfter time.Duration) *tagsCache { } } -// returns true if still valid (not expired) and tags list. +// Get returns true if still valid (not expired) and tags list. func (c *tagsCache) Get(repo string) (bool, []string) { c.mu.Lock() defer c.mu.Unlock() diff --git a/pkg/extensions/sync/service.go b/pkg/extensions/sync/service.go index 719d0391..816976c4 100644 --- a/pkg/extensions/sync/service.go +++ b/pkg/extensions/sync/service.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync @@ -9,6 +8,7 @@ import ( "fmt" "net/http" "net/url" + "slices" "strconv" "strings" "sync" @@ -397,7 +397,7 @@ func (service *BaseService) SyncReferrers(ctx context.Context, repo string, return nil } -// sync repo periodically. +// SyncRepo syncs repo periodically. func (service *BaseService) SyncRepo(ctx context.Context, repo string) error { service.log.Info().Str("repo", repo).Str("registry", service.remote.GetHostName()). Msg("sync: syncing repo") @@ -590,7 +590,7 @@ func (service *BaseService) syncImage(ctx context.Context, localRepo, remoteRepo } // verify repo contains a cosign signature for this manifest - hasCosignSignature := common.Contains(repoTags, fmt.Sprintf("%s-%s.sig", remoteDigest.Algorithm(), + hasCosignSignature := slices.Contains(repoTags, fmt.Sprintf("%s-%s.sig", remoteDigest.Algorithm(), remoteDigest.Encoded())) isSigned := hasSignatureReferrers(referrers) || hasCosignSignature @@ -721,7 +721,7 @@ func (service *BaseService) syncReferrers(ctx context.Context, tags []string, lo } // is seen - if common.Contains(seen, remoteDigest.String()) { + if slices.Contains(seen, remoteDigest.String()) { return nil } diff --git a/pkg/extensions/sync/sync.go b/pkg/extensions/sync/sync.go index d8dbda0b..eaf8adfe 100644 --- a/pkg/extensions/sync/sync.go +++ b/pkg/extensions/sync/sync.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync @@ -20,7 +19,7 @@ import ( // below types are used by regclient to copy images // ref.Ref- describes a registry/repo:tag -// Sync general functionalities, one service per registry config. +// Service provides sync general functionalities, one service per registry config. type Service interface { // Get next repo from remote /v2/_catalog, will return empty string when there is no repo left. GetNextRepo(lastRepo string) (string, error) // used by task scheduler @@ -39,7 +38,7 @@ type Service interface { GetSyncTimeout() time.Duration } -// Local and remote registries must implement this interface. +// Registry interface must be implemented by local and remote registries. type Registry interface { // Get temporary ImageReference, is used by functions in regclient package GetImageReference(repo string, tag string) (ref.Ref, error) @@ -62,7 +61,7 @@ type CredentialHelper interface { } /* -Temporary oci layout, sync first pulls an image to this oci layout (using oci:// transport) +OciLayoutStorage is a temporary oci layout, sync first pulls an image to this oci layout (using oci:// transport) then moves them into ImageStore. */ type OciLayoutStorage interface { @@ -85,7 +84,7 @@ type Remote interface { GetDigest(ctx context.Context, repo, tag string) (godigest.Digest, error) } -// Local registry. +// Destination is a local registry. type Destination interface { Registry // Check if descriptors are already synced diff --git a/pkg/extensions/sync/sync_disabled_test.go b/pkg/extensions/sync/sync_disabled_test.go index 458ece0e..b2cc7f0c 100644 --- a/pkg/extensions/sync/sync_disabled_test.go +++ b/pkg/extensions/sync/sync_disabled_test.go @@ -1,5 +1,4 @@ //go:build !sync -// +build !sync package sync_test diff --git a/pkg/extensions/sync/sync_internal_test.go b/pkg/extensions/sync/sync_internal_test.go index 05f380ea..5bc914d0 100644 --- a/pkg/extensions/sync/sync_internal_test.go +++ b/pkg/extensions/sync/sync_internal_test.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync @@ -225,7 +224,7 @@ func TestService(t *testing.T) { // Step 1: Verify empty requestStore initially initialImageCount := 0 - onDemand.requestStore.Range(func(key, value interface{}) bool { + onDemand.requestStore.Range(func(key, value any) bool { initialImageCount++ return true }) @@ -242,7 +241,7 @@ func TestService(t *testing.T) { // Step 3: Verify we now have 1 request preImageCount := 0 - onDemand.requestStore.Range(func(key, value interface{}) bool { + onDemand.requestStore.Range(func(key, value any) bool { preImageCount++ return true }) @@ -254,7 +253,7 @@ func TestService(t *testing.T) { // Step 5: Verify CONTINUE PATH EXECUTED - no new requests created postImageCount := 0 - onDemand.requestStore.Range(func(key, value interface{}) bool { + onDemand.requestStore.Range(func(key, value any) bool { postImageCount++ return true }) @@ -267,7 +266,7 @@ func TestService(t *testing.T) { // Step 7: Verify current state before referrer test - we should have 1 request initialReferrerCount := 0 - onDemand.requestStore.Range(func(key, value interface{}) bool { + onDemand.requestStore.Range(func(key, value any) bool { initialReferrerCount++ return true }) @@ -284,7 +283,7 @@ func TestService(t *testing.T) { // Step 9: Verify we now have 2 requests (image + referrer) preReferrerCount := 0 - onDemand.requestStore.Range(func(key, value interface{}) bool { + onDemand.requestStore.Range(func(key, value any) bool { preReferrerCount++ return true }) @@ -296,7 +295,7 @@ func TestService(t *testing.T) { // Step 11: Verify CONTINUE PATH EXECUTED - no new referrer requests created postReferrerCount := 0 - onDemand.requestStore.Range(func(key, value interface{}) bool { + onDemand.requestStore.Range(func(key, value any) bool { postReferrerCount++ return true }) @@ -309,7 +308,7 @@ func TestService(t *testing.T) { // Step 13: Final verification - exactly 2 requests total (both pre-populated, none deleted) finalCount := 0 - onDemand.requestStore.Range(func(key, value interface{}) bool { + onDemand.requestStore.Range(func(key, value any) bool { finalCount++ return true }) @@ -434,7 +433,7 @@ func TestService(t *testing.T) { // Verify initial requestStore is empty initialCount := 0 - onDemand.requestStore.Range(func(key, value interface{}) bool { + onDemand.requestStore.Range(func(key, value any) bool { initialCount++ return true }) @@ -475,7 +474,7 @@ func TestService(t *testing.T) { // Verify initial requestStore is empty initialCount := 0 - onDemand.requestStore.Range(func(key, value interface{}) bool { + onDemand.requestStore.Range(func(key, value any) bool { initialCount++ return true }) diff --git a/pkg/extensions/sync/sync_test.go b/pkg/extensions/sync/sync_test.go index 408c384e..0bbe232e 100644 --- a/pkg/extensions/sync/sync_test.go +++ b/pkg/extensions/sync/sync_test.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync_test @@ -5638,7 +5637,7 @@ func TestOnDemandMultipleImage(t *testing.T) { defer dcm.StopServer() callsNo := 5 - for i := 0; i < callsNo; i++ { + for range callsNo { _, _ = destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) } @@ -5801,7 +5800,7 @@ func TestOnDemandPullsReferrersOnce(t *testing.T) { targetURL := destBaseURL + "/v2/" + testImage + "/referrers/" + digest - for i := 0; i < numConcurrentRequests; i++ { + for i := range numConcurrentRequests { go func(routineID int) { defer wg.Done() t.Logf("Goroutine %d: Sending request to %s", routineID, targetURL) @@ -5928,7 +5927,7 @@ func TestOnDemandPullsOnce(t *testing.T) { targetURL := destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag - for i := 0; i < numConcurrentRequests; i++ { + for i := range numConcurrentRequests { go func(routineID int) { defer wg.Done() t.Logf("Goroutine %d: Sending request to %s", routineID, targetURL) diff --git a/pkg/extensions/sync/utils.go b/pkg/extensions/sync/utils.go index fb82a78a..945a8881 100644 --- a/pkg/extensions/sync/utils.go +++ b/pkg/extensions/sync/utils.go @@ -1,5 +1,4 @@ //go:build sync -// +build sync package sync diff --git a/pkg/log/log.go b/pkg/log/log.go index 72af6e23..d97d82f1 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -162,14 +162,14 @@ func (e *Event) Err(err error) *Event { } // Interface adds any interface field to the event. -func (e *Event) Interface(key string, val interface{}) *Event { +func (e *Event) Interface(key string, val any) *Event { e.attrs = append(e.attrs, slog.Any(key, val)) return e } // Any adds any interface field to the event (alias for Interface). -func (e *Event) Any(key string, val interface{}) *Event { +func (e *Event) Any(key string, val any) *Event { return e.Interface(key, val) } @@ -181,7 +181,7 @@ func (e *Event) Strs(key string, vals []string) *Event { } // IPAddr adds an IP address field to the event. -func (e *Event) IPAddr(key string, ip interface{}) *Event { +func (e *Event) IPAddr(key string, ip any) *Event { e.attrs = append(e.attrs, slog.String(key, fmt.Sprintf("%v", ip))) return e @@ -214,7 +214,7 @@ func NewTestLoggerPtr() *Logger { } // Msgf logs the event with a formatted message. -func (e *Event) Msgf(format string, args ...interface{}) { +func (e *Event) Msgf(format string, args ...any) { msg := fmt.Sprintf(format, args...) // Create a new slice to avoid modifying the original diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go index e53c8ad1..d9869e52 100644 --- a/pkg/log/log_test.go +++ b/pkg/log/log_test.go @@ -1,5 +1,4 @@ //go:build sync && scrub && metrics && search -// +build sync,scrub,metrics,search package log_test diff --git a/pkg/meta/boltdb/boltdb.go b/pkg/meta/boltdb/boltdb.go index 936a1e57..b5ecbf10 100644 --- a/pkg/meta/boltdb/boltdb.go +++ b/pkg/meta/boltdb/boltdb.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "slices" "strings" "time" @@ -464,8 +465,8 @@ func (bdw *BoltDB) SearchRepos(ctx context.Context, searchText string, } protoRepoMeta.Rank = int32(rank) //nolint:gosec // ignore overflow - protoRepoMeta.IsStarred = zcommon.Contains(userStars, protoRepoMeta.Name) - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, protoRepoMeta.Name) + protoRepoMeta.IsStarred = slices.Contains(userStars, protoRepoMeta.Name) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, protoRepoMeta.Name) repos = append(repos, mConvert.GetRepoMeta(protoRepoMeta)) } @@ -574,8 +575,8 @@ func (bdw *BoltDB) SearchTags(ctx context.Context, searchText string, delete(protoRepoMeta.Tags, "") - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, protoRepoMeta.Name) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, protoRepoMeta.Name) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, protoRepoMeta.Name) + protoRepoMeta.IsStarred = slices.Contains(userStars, protoRepoMeta.Name) for tag, descriptor := range protoRepoMeta.Tags { if !strings.HasPrefix(tag, searchedTag) || tag == "" { @@ -658,8 +659,8 @@ func (bdw *BoltDB) FilterTags(ctx context.Context, filterRepoTag mTypes.FilterRe } delete(protoRepoMeta.Tags, "") - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, protoRepoMeta.Name) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, protoRepoMeta.Name) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, protoRepoMeta.Name) + protoRepoMeta.IsStarred = slices.Contains(userStars, protoRepoMeta.Name) repoMeta := mConvert.GetRepoMeta(protoRepoMeta) for tag, descriptor := range protoRepoMeta.Tags { @@ -759,8 +760,8 @@ func (bdw *BoltDB) FilterRepos(ctx context.Context, acceptName mTypes.FilterRepo return err } - repoMeta.IsBookmarked = zcommon.Contains(userBookmarks, repoMeta.Name) - repoMeta.IsStarred = zcommon.Contains(userStars, repoMeta.Name) + repoMeta.IsBookmarked = slices.Contains(userBookmarks, repoMeta.Name) + repoMeta.IsStarred = slices.Contains(userStars, repoMeta.Name) fullRepoMeta := mConvert.GetRepoMeta(repoMeta) @@ -796,8 +797,8 @@ func (bdw *BoltDB) GetRepoMeta(ctx context.Context, repo string) (mTypes.RepoMet } delete(protoRepoMeta.Tags, "") - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, repo) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, repo) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, repo) + protoRepoMeta.IsStarred = slices.Contains(userStars, repo) return nil }) @@ -830,8 +831,8 @@ func (bdw *BoltDB) GetFullImageMeta(ctx context.Context, repo string, tag string } delete(protoRepoMeta.Tags, "") - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, repo) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, repo) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, repo) + protoRepoMeta.IsStarred = slices.Contains(userStars, repo) descriptor, ok := protoRepoMeta.Tags[tag] if !ok { @@ -1518,7 +1519,7 @@ func (bdw *BoltDB) ToggleStarRepo(ctx context.Context, repo string) (mTypes.Togg return err } - isRepoStarred := zcommon.Contains(userData.StarredRepos, repo) + isRepoStarred := slices.Contains(userData.StarredRepos, repo) if isRepoStarred { res = mTypes.Removed @@ -1591,7 +1592,7 @@ func (bdw *BoltDB) ToggleBookmarkRepo(ctx context.Context, repo string) (mTypes. return err } - isRepoBookmarked := zcommon.Contains(userData.BookmarkedRepos, repo) + isRepoBookmarked := slices.Contains(userData.BookmarkedRepos, repo) if isRepoBookmarked { res = mTypes.Removed diff --git a/pkg/meta/common/common.go b/pkg/meta/common/common.go index c9f69663..d37dc9e4 100644 --- a/pkg/meta/common/common.go +++ b/pkg/meta/common/common.go @@ -1,6 +1,7 @@ package common import ( + "slices" "strings" "time" @@ -15,23 +16,15 @@ import ( ) func SignatureAlreadyExists(signatureSlice []mTypes.SignatureInfo, sm mTypes.SignatureMetadata) bool { - for _, sigInfo := range signatureSlice { - if sm.SignatureDigest == sigInfo.SignatureManifestDigest { - return true - } - } - - return false + return slices.ContainsFunc(signatureSlice, func(sigInfo mTypes.SignatureInfo) bool { + return sm.SignatureDigest == sigInfo.SignatureManifestDigest + }) } func ProtoSignatureAlreadyExists(signatureSlice []*proto_go.SignatureInfo, sm mTypes.SignatureMetadata) bool { - for _, sigInfo := range signatureSlice { - if sm.SignatureDigest == sigInfo.SignatureManifestDigest { - return true - } - } - - return false + return slices.ContainsFunc(signatureSlice, func(sigInfo *proto_go.SignatureInfo) bool { + return sm.SignatureDigest == sigInfo.SignatureManifestDigest + }) } func ReferenceIsDigest(reference string) bool { @@ -159,19 +152,9 @@ func MatchesArtifactTypes(descriptorMediaType string, artifactTypes []string) bo return true } - found := false - - for _, artifactType := range artifactTypes { - if artifactType != "" && descriptorMediaType != artifactType { - continue - } - - found = true - - break - } - - return found + return slices.ContainsFunc(artifactTypes, func(artifactType string) bool { + return artifactType == "" || descriptorMediaType == artifactType + }) } // CheckImageLastUpdated check if the given image is updated earlier than the current repoLastUpdated value diff --git a/pkg/meta/convert/convert.go b/pkg/meta/convert/convert.go index 28d0879a..1adc6856 100644 --- a/pkg/meta/convert/convert.go +++ b/pkg/meta/convert/convert.go @@ -1,6 +1,7 @@ package convert import ( + "slices" "time" godigest "github.com/opencontainers/go-digest" @@ -8,7 +9,6 @@ import ( ispec "github.com/opencontainers/image-spec/specs-go/v1" "google.golang.org/protobuf/types/known/timestamppb" - "zotregistry.dev/zot/v2/pkg/common" "zotregistry.dev/zot/v2/pkg/compat" proto_go "zotregistry.dev/zot/v2/pkg/meta/proto/gen" mTypes "zotregistry.dev/zot/v2/pkg/meta/types" @@ -497,18 +497,14 @@ func AddProtoPlatforms(platforms []*proto_go.Platform, newPlatforms []*proto_go. } func ContainsProtoPlatform(platforms []*proto_go.Platform, platform *proto_go.Platform) bool { - for i := range platforms { - if platforms[i].GetOS() == platform.GetOS() && platforms[i].GetArchitecture() == platform.GetArchitecture() { - return true - } - } - - return false + return slices.ContainsFunc(platforms, func(p *proto_go.Platform) bool { + return p.GetOS() == platform.GetOS() && p.GetArchitecture() == platform.GetArchitecture() + }) } func AddVendors(vendors []string, newVendors []string) []string { for _, newVendor := range newVendors { - if !common.Contains(vendors, newVendor) { + if !slices.Contains(vendors, newVendor) { vendors = append(vendors, newVendor) } } diff --git a/pkg/meta/convert/convert_proto.go b/pkg/meta/convert/convert_proto.go index f0f3493a..481ae813 100644 --- a/pkg/meta/convert/convert_proto.go +++ b/pkg/meta/convert/convert_proto.go @@ -213,8 +213,6 @@ func getProtoManifestLayers(layers []ispec.Descriptor) []*proto_go.Descriptor { protoLayers := []*proto_go.Descriptor{} for _, layer := range layers { - layer := layer - protoLayers = append(protoLayers, getProtoDesc(&layer)) } @@ -275,8 +273,6 @@ func getProtoHistory(historySlice []ispec.History) []*proto_go.History { protoHistory := []*proto_go.History{} for _, history := range historySlice { - history := history - protoHistory = append(protoHistory, &proto_go.History{ Created: GetProtoTime(history.Created), CreatedBy: &history.CreatedBy, diff --git a/pkg/meta/dynamodb/dynamodb.go b/pkg/meta/dynamodb/dynamodb.go index 818f4427..1602c477 100644 --- a/pkg/meta/dynamodb/dynamodb.go +++ b/pkg/meta/dynamodb/dynamodb.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "slices" "strings" "time" @@ -635,8 +636,8 @@ func (dwr *DynamoDB) SearchRepos(ctx context.Context, searchText string) ([]mTyp } protoRepoMeta.Rank = int32(rank) //nolint:gosec // ignore overflow - protoRepoMeta.IsStarred = zcommon.Contains(userStars, protoRepoMeta.Name) - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, protoRepoMeta.Name) + protoRepoMeta.IsStarred = slices.Contains(userStars, protoRepoMeta.Name) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, protoRepoMeta.Name) repos = append(repos, mConvert.GetRepoMeta(protoRepoMeta)) } @@ -670,8 +671,8 @@ func (dwr *DynamoDB) SearchTags(ctx context.Context, searchText string) ([]mType delete(protoRepoMeta.Tags, "") - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, searchedRepo) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, searchedRepo) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, searchedRepo) + protoRepoMeta.IsStarred = slices.Contains(userStars, searchedRepo) for tag, descriptor := range protoRepoMeta.Tags { if !strings.HasPrefix(tag, searchedTag) { @@ -754,8 +755,8 @@ func (dwr *DynamoDB) FilterTags(ctx context.Context, filterRepoTag mTypes.Filter continue } - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, protoRepoMeta.Name) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, protoRepoMeta.Name) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, protoRepoMeta.Name) + protoRepoMeta.IsStarred = slices.Contains(userStars, protoRepoMeta.Name) repoMeta := mConvert.GetRepoMeta(protoRepoMeta) for tag, descriptor := range repoMeta.Tags { @@ -890,8 +891,8 @@ func (dwr *DynamoDB) GetRepoMeta(ctx context.Context, repo string) (mTypes.RepoM userBookmarks := getUserBookmarks(ctx, dwr) userStars := getUserStars(ctx, dwr) - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, repo) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, repo) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, repo) + protoRepoMeta.IsStarred = slices.Contains(userStars, repo) return mConvert.GetRepoMeta(protoRepoMeta), nil } @@ -906,8 +907,8 @@ func (dwr *DynamoDB) GetFullImageMeta(ctx context.Context, repo string, tag stri bookmarks, stars := dwr.getUserBookmarksAndStars(ctx) - protoRepoMeta.IsBookmarked = zcommon.Contains(bookmarks, repo) - protoRepoMeta.IsStarred = zcommon.Contains(stars, repo) + protoRepoMeta.IsBookmarked = slices.Contains(bookmarks, repo) + protoRepoMeta.IsStarred = slices.Contains(stars, repo) descriptor, ok := protoRepoMeta.Tags[tag] if !ok { @@ -1040,8 +1041,8 @@ func (dwr *DynamoDB) FilterRepos(ctx context.Context, acceptName mTypes.FilterRe continue } - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, protoRepoMeta.Name) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, protoRepoMeta.Name) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, protoRepoMeta.Name) + protoRepoMeta.IsStarred = slices.Contains(userStars, protoRepoMeta.Name) fullRepoMeta := mConvert.GetRepoMeta(protoRepoMeta) @@ -1574,7 +1575,7 @@ func (dwr *DynamoDB) ToggleBookmarkRepo(ctx context.Context, repo string) ( return res, err } - if !zcommon.Contains(userData.BookmarkedRepos, repo) { + if !slices.Contains(userData.BookmarkedRepos, repo) { userData.BookmarkedRepos = append(userData.BookmarkedRepos, repo) res = mTypes.Added } else { @@ -1625,7 +1626,7 @@ func (dwr *DynamoDB) ToggleStarRepo(ctx context.Context, repo string) ( return res, err } - if !zcommon.Contains(userData.StarredRepos, repo) { + if !slices.Contains(userData.StarredRepos, repo) { userData.StarredRepos = append(userData.StarredRepos, repo) res = mTypes.Added } else { diff --git a/pkg/meta/dynamodb/dynamodb_internal_test.go b/pkg/meta/dynamodb/dynamodb_internal_test.go index abde6b9c..3e21d3d3 100644 --- a/pkg/meta/dynamodb/dynamodb_internal_test.go +++ b/pkg/meta/dynamodb/dynamodb_internal_test.go @@ -38,7 +38,7 @@ func TestWrapperErrors(t *testing.T) { badEndpoint := endpoint + "1" customResolver := aws.EndpointResolverWithOptionsFunc( //nolint: staticcheck - func(service, region string, options ...interface{}) (aws.Endpoint, error) { + func(service, region string, options ...any) (aws.Endpoint, error) { return aws.Endpoint{ //nolint: staticcheck PartitionID: "aws", URL: badEndpoint, @@ -74,7 +74,7 @@ func TestWrapperErrors(t *testing.T) { Convey("Delete table errors", t, func() { customResolver := aws.EndpointResolverWithOptionsFunc( //nolint: staticcheck - func(service, region string, options ...interface{}) (aws.Endpoint, error) { + func(service, region string, options ...any) (aws.Endpoint, error) { return aws.Endpoint{ //nolint: staticcheck PartitionID: "aws", URL: endpoint, diff --git a/pkg/meta/dynamodb/dynamodb_test.go b/pkg/meta/dynamodb/dynamodb_test.go index 91e91acd..c5ba12b6 100644 --- a/pkg/meta/dynamodb/dynamodb_test.go +++ b/pkg/meta/dynamodb/dynamodb_test.go @@ -106,7 +106,7 @@ func TestIterator(t *testing.T) { func TestIteratorErrors(t *testing.T) { Convey("errors", t, func() { customResolver := aws.EndpointResolverWithOptionsFunc( //nolint: staticcheck - func(service, region string, options ...interface{}) (aws.Endpoint, error) { + func(service, region string, options ...any) (aws.Endpoint, error) { return aws.Endpoint{ //nolint: staticcheck PartitionID: "aws", URL: "endpoint", diff --git a/pkg/meta/dynamodb/parameters.go b/pkg/meta/dynamodb/parameters.go index 0df55c9c..d97872da 100644 --- a/pkg/meta/dynamodb/parameters.go +++ b/pkg/meta/dynamodb/parameters.go @@ -15,7 +15,7 @@ type DBDriverParameters struct { func GetDynamoClient(params DBDriverParameters) (*dynamodb.Client, error) { customResolver := aws.EndpointResolverWithOptionsFunc( //nolint: staticcheck - func(service, region string, options ...interface{}) (aws.Endpoint, error) { + func(service, region string, options ...any) (aws.Endpoint, error) { return aws.Endpoint{ //nolint: staticcheck PartitionID: "aws", URL: params.Endpoint, diff --git a/pkg/meta/meta.go b/pkg/meta/meta.go index 35be9408..9d83dc57 100644 --- a/pkg/meta/meta.go +++ b/pkg/meta/meta.go @@ -60,7 +60,7 @@ func New(storageConfig config.StorageConfig, log log.Logger) (mTypes.MetaDB, err return boltdb.New(driver, log) //nolint:contextcheck } -func getDynamoParams(cacheDriverConfig map[string]interface{}, log log.Logger) mdynamodb.DBDriverParameters { +func getDynamoParams(cacheDriverConfig map[string]any, log log.Logger) mdynamodb.DBDriverParameters { allParametersOk := true endpoint, ok := toStringIfOk(cacheDriverConfig, "endpoint", "", log) @@ -103,7 +103,7 @@ func getDynamoParams(cacheDriverConfig map[string]interface{}, log log.Logger) m } } -func getRedisParams(cacheDriverConfig map[string]interface{}, log log.Logger) redis.DBDriverParameters { +func getRedisParams(cacheDriverConfig map[string]any, log log.Logger) redis.DBDriverParameters { keyPrefix, ok := toStringIfOk(cacheDriverConfig, "keyprefix", "zot", log) if !ok { log.Panic().Msg("redis parameters are not specified correctly, can't proceed") @@ -114,7 +114,7 @@ func getRedisParams(cacheDriverConfig map[string]interface{}, log log.Logger) re } } -func toStringIfOk(cacheDriverConfig map[string]interface{}, +func toStringIfOk(cacheDriverConfig map[string]any, param string, defaultVal string, log log.Logger, diff --git a/pkg/meta/meta_test.go b/pkg/meta/meta_test.go index 480f4611..5153c427 100644 --- a/pkg/meta/meta_test.go +++ b/pkg/meta/meta_test.go @@ -1,5 +1,4 @@ //go:build imagetrust -// +build imagetrust package meta_test @@ -9,6 +8,7 @@ import ( "fmt" "os" "path" + "slices" "testing" "time" @@ -178,7 +178,7 @@ func TestRedisDB(t *testing.T) { log := log.NewTestLogger() params := redis.DBDriverParameters{KeyPrefix: "zot"} - driverConfig := map[string]interface{}{"url": "redis://" + miniRedis.Addr()} + driverConfig := map[string]any{"url": "redis://" + miniRedis.Addr()} redisDriver, err := rediscfg.GetRedisClient(driverConfig, log) So(err, ShouldBeNil) @@ -2312,13 +2312,13 @@ func RunMetaDBTests(t *testing.T, metaDB mTypes.MetaDB, preparationFuncs ...func } } - So(zcommon.Contains(tags, "0.0.1"), ShouldBeTrue) - So(zcommon.Contains(tags, "0.0.2"), ShouldBeTrue) - So(zcommon.Contains(tags, "0.1.0"), ShouldBeTrue) - So(zcommon.Contains(tags, "1.0.0"), ShouldBeTrue) - So(zcommon.Contains(tags, "1.0.1"), ShouldBeTrue) - So(zcommon.Contains(tags, "2.0.0"), ShouldBeTrue) - So(zcommon.Contains(tags, "0.0.1"), ShouldBeTrue) + So(slices.Contains(tags, "0.0.1"), ShouldBeTrue) + So(slices.Contains(tags, "0.0.2"), ShouldBeTrue) + So(slices.Contains(tags, "0.1.0"), ShouldBeTrue) + So(slices.Contains(tags, "1.0.0"), ShouldBeTrue) + So(slices.Contains(tags, "1.0.1"), ShouldBeTrue) + So(slices.Contains(tags, "2.0.0"), ShouldBeTrue) + So(slices.Contains(tags, "0.0.1"), ShouldBeTrue) So(indexImage.Digest.String(), ShouldResemble, multiarch.DigestStr()) @@ -3120,16 +3120,16 @@ func TestCreateBoltDB(t *testing.T) { So(log, ShouldNotBeNil) Convey("Test New() with unspecified driver", func() { - conf.Storage.CacheDriver = map[string]interface{}{} + conf.Storage.CacheDriver = map[string]any{} }) Convey("Test New() with bad driver", func() { // we default to bolt in case of misconfiguration - conf.Storage.CacheDriver = map[string]interface{}{"name": "somedriver"} + conf.Storage.CacheDriver = map[string]any{"name": "somedriver"} }) Convey("Test New() with specified driver", func() { - conf.Storage.CacheDriver = map[string]interface{}{"name": "cache"} + conf.Storage.CacheDriver = map[string]any{"name": "cache"} }) repoDBPath := path.Join(rootDir, "meta.db") @@ -3162,7 +3162,7 @@ func TestCreateRedisDB(t *testing.T) { Convey("Succeeds with default key prefix", func() { miniRedis := miniredis.RunT(t) - cacheDriverParams := map[string]interface{}{ + cacheDriverParams := map[string]any{ "name": "redis", "url": "redis://" + miniRedis.Addr(), } @@ -3177,7 +3177,7 @@ func TestCreateRedisDB(t *testing.T) { Convey("Succeeds with specific key prefix", func() { miniRedis := miniredis.RunT(t) - cacheDriverParams := map[string]interface{}{ + cacheDriverParams := map[string]any{ "name": "redis", "url": "redis://" + miniRedis.Addr(), "key": "keyPrefix", @@ -3192,7 +3192,7 @@ func TestCreateRedisDB(t *testing.T) { Convey("Fails on Ping()", func() { // Redis client will not be responding - cacheDriverParams := map[string]interface{}{ + cacheDriverParams := map[string]any{ "name": "redis", "url": "redis://127.0.0.1:" + tCommon.GetFreePort(), } @@ -3205,7 +3205,7 @@ func TestCreateRedisDB(t *testing.T) { Convey("Fail on invalid parameters", func() { // Bad key types - cacheDriverParams := map[string]interface{}{ + cacheDriverParams := map[string]any{ "name": "redis", "url": "redis://127.0.0.1:" + tCommon.GetFreePort(), "keyprefix": true, @@ -3216,7 +3216,7 @@ func TestCreateRedisDB(t *testing.T) { testFunc := func() { _, _ = meta.New(conf.Storage.StorageConfig, log) } So(testFunc, ShouldPanic) - cacheDriverParams = map[string]interface{}{ + cacheDriverParams = map[string]any{ "name": "redis", "url": "redis://127.0.0.1:" + tCommon.GetFreePort(), "keyprefix": "", @@ -3227,7 +3227,7 @@ func TestCreateRedisDB(t *testing.T) { testFunc = func() { _, _ = meta.New(conf.Storage.StorageConfig, log) } So(testFunc, ShouldPanic) - cacheDriverParams = map[string]interface{}{ + cacheDriverParams = map[string]any{ "name": "redis", "url": false, "keyprefix": "zot", diff --git a/pkg/meta/parse.go b/pkg/meta/parse.go index 50bc0184..ea6d3a28 100644 --- a/pkg/meta/parse.go +++ b/pkg/meta/parse.go @@ -90,7 +90,7 @@ func ParseStorage(metaDB mTypes.MetaDB, storeController stypes.StoreController, func getReposToBeDeleted(allStorageRepos []string, allMetaDBRepos []string) []string { toBeDeleted := []string{} - storageRepoNameSet := map[string]struct{}{} + storageRepoNameSet := make(map[string]struct{}, len(allStorageRepos)) for i := range allStorageRepos { storageRepoNameSet[allStorageRepos[i]] = struct{}{} @@ -313,7 +313,7 @@ func getNotationSignatureLayersInfo( return layers, nil } -// SetMetadataFromInput tries to set manifest metadata and update repo metadata by adding the current tag +// SetImageMetaFromInput tries to set manifest metadata and update repo metadata by adding the current tag // (in case the reference is a tag). The function expects image manifests and indexes (multi arch images). func SetImageMetaFromInput(ctx context.Context, repo, reference, mediaType string, digest godigest.Digest, blob []byte, imageStore stypes.ImageStore, metaDB mTypes.MetaDB, log log.Logger, diff --git a/pkg/meta/parse_test.go b/pkg/meta/parse_test.go index 8a47baa2..90824006 100644 --- a/pkg/meta/parse_test.go +++ b/pkg/meta/parse_test.go @@ -379,7 +379,7 @@ func TestParseStorageWithRedisDB(t *testing.T) { log := log.NewTestLogger() params := redis.DBDriverParameters{KeyPrefix: "zot"} - driverConfig := map[string]interface{}{"url": "redis://" + miniRedis.Addr()} + driverConfig := map[string]any{"url": "redis://" + miniRedis.Addr()} redisDriver, err := rediscfg.GetRedisClient(driverConfig, log) So(err, ShouldBeNil) @@ -439,7 +439,7 @@ func RunParseStorageTests(rootDir string, metaDB mTypes.MetaDB, log log.Logger) storeController := storage.StoreController{DefaultStore: imageStore} manifests := []ispec.Manifest{} - for i := 0; i < 3; i++ { + for i := range 3 { image := CreateRandomImage() //nolint:staticcheck manifests = append(manifests, image.Manifest) diff --git a/pkg/meta/redis/redis.go b/pkg/meta/redis/redis.go index ece03419..d44eb0f3 100644 --- a/pkg/meta/redis/redis.go +++ b/pkg/meta/redis/redis.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "slices" "strings" "time" @@ -141,7 +142,7 @@ func (rc *RedisDB) ToggleStarRepo(ctx context.Context, repo string) (mTypes.Togg return err } - isRepoStarred := zcommon.Contains(userData.StarredRepos, repo) + isRepoStarred := slices.Contains(userData.StarredRepos, repo) if isRepoStarred { res = mTypes.Removed @@ -228,7 +229,7 @@ func (rc *RedisDB) ToggleBookmarkRepo(ctx context.Context, repo string) (mTypes. return err } - isRepoBookmarked := zcommon.Contains(userData.BookmarkedRepos, repo) + isRepoBookmarked := slices.Contains(userData.BookmarkedRepos, repo) if isRepoBookmarked { res = mTypes.Removed @@ -263,7 +264,6 @@ func (rc *RedisDB) ToggleBookmarkRepo(ctx context.Context, repo string) (mTypes. return res, err } -// UserDB profile/api key CRUD. func (rc *RedisDB) GetUserData(ctx context.Context) (mTypes.UserData, error) { userData := mTypes.UserData{} userData.APIKeys = make(map[string]mTypes.APIKeyDetails) @@ -943,8 +943,8 @@ func (rc *RedisDB) SearchRepos(ctx context.Context, searchText string) ([]mTypes } protoRepoMeta.Rank = int32(rank) //nolint:gosec // ignore overflow - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, protoRepoMeta.Name) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, protoRepoMeta.Name) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, protoRepoMeta.Name) + protoRepoMeta.IsStarred = slices.Contains(userStars, protoRepoMeta.Name) repoMeta := mConvert.GetRepoMeta(protoRepoMeta) foundRepos = append(foundRepos, repoMeta) @@ -987,8 +987,8 @@ func (rc *RedisDB) SearchTags(ctx context.Context, searchText string) ([]mTypes. delete(protoRepoMeta.Tags, "") - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, protoRepoMeta.Name) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, protoRepoMeta.Name) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, protoRepoMeta.Name) + protoRepoMeta.IsStarred = slices.Contains(userStars, protoRepoMeta.Name) for tag, descriptor := range protoRepoMeta.Tags { if !strings.HasPrefix(tag, searchedTag) || tag == "" { @@ -1069,8 +1069,8 @@ func (rc *RedisDB) FilterTags(ctx context.Context, filterRepoTag mTypes.FilterRe } delete(protoRepoMeta.Tags, "") - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, protoRepoMeta.Name) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, protoRepoMeta.Name) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, protoRepoMeta.Name) + protoRepoMeta.IsStarred = slices.Contains(userStars, protoRepoMeta.Name) repoMeta := mConvert.GetRepoMeta(protoRepoMeta) for tag, descriptor := range protoRepoMeta.Tags { @@ -1170,8 +1170,8 @@ func (rc *RedisDB) FilterRepos(ctx context.Context, acceptName mTypes.FilterRepo return []mTypes.RepoMeta{}, err } - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, protoRepoMeta.Name) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, protoRepoMeta.Name) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, protoRepoMeta.Name) + protoRepoMeta.IsStarred = slices.Contains(userStars, protoRepoMeta.Name) repoMeta := mConvert.GetRepoMeta(protoRepoMeta) @@ -1193,8 +1193,8 @@ func (rc *RedisDB) GetRepoMeta(ctx context.Context, repo string) (mTypes.RepoMet userBookmarks, userStars := rc.getUserBookmarksAndStarsNoError(ctx) delete(protoRepoMeta.Tags, "") - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, repo) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, repo) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, repo) + protoRepoMeta.IsStarred = slices.Contains(userStars, repo) return mConvert.GetRepoMeta(protoRepoMeta), err } @@ -1211,8 +1211,8 @@ func (rc *RedisDB) GetFullImageMeta(ctx context.Context, repo string, tag string userBookmarks, userStars := rc.getUserBookmarksAndStarsNoError(ctx) delete(protoRepoMeta.Tags, "") - protoRepoMeta.IsBookmarked = zcommon.Contains(userBookmarks, repo) - protoRepoMeta.IsStarred = zcommon.Contains(userStars, repo) + protoRepoMeta.IsBookmarked = slices.Contains(userBookmarks, repo) + protoRepoMeta.IsStarred = slices.Contains(userStars, repo) descriptor, ok := protoRepoMeta.Tags[tag] if !ok { @@ -1840,14 +1840,11 @@ func (rc *RedisDB) FilterImageMeta(ctx context.Context, return imageMetaMap, nil } -/* - RemoveRepoReference removes the tag from RepoMetadata if the reference is a tag, - -it also removes its corresponding digest from Statistics, Signatures and Referrers if there are no tags -pointing to it. -If the reference is a digest then it will remove the digest from Statistics, Signatures and Referrers only -if there are no tags pointing to the digest, otherwise it's noop. -*/ +// RemoveRepoReference removes the tag from RepoMetadata if the reference is a tag. +// It also removes its corresponding digest from Statistics, Signatures and Referrers if there are no tags +// pointing to it. +// If the reference is a digest then it will remove the digest from Statistics, Signatures and Referrers only +// if there are no tags pointing to the digest, otherwise it's noop. func (rc *RedisDB) RemoveRepoReference(repo, reference string, manifestDigest godigest.Digest) error { ctx := context.Background() diff --git a/pkg/meta/types/types.go b/pkg/meta/types/types.go index f6bbcdba..6e16b311 100644 --- a/pkg/meta/types/types.go +++ b/pkg/meta/types/types.go @@ -8,7 +8,7 @@ import ( ispec "github.com/opencontainers/image-spec/specs-go/v1" ) -// Used to model changes to an object after a call to the DB. +// ToggleState is used to model changes to an object after a call to the DB. type ToggleState int const ( @@ -18,6 +18,7 @@ const ( ) type ( + // FilterFunc is a filter function. // Currently imageMeta applied for indexes is applied for each manifest individually so imageMeta.manifests // contains just 1 manifest. FilterFunc func(repoMeta RepoMeta, imageMeta ImageMeta) bool @@ -284,6 +285,7 @@ type FullManifestMeta struct { type LastUpdatedImage struct { Descriptor + Tag string LastUpdated *time.Time } diff --git a/pkg/regexp/regexp.go b/pkg/regexp/regexp.go index a9efd538..ee30045e 100644 --- a/pkg/regexp/regexp.go +++ b/pkg/regexp/regexp.go @@ -1,6 +1,9 @@ package regexp -import "regexp" +import ( + "regexp" + "strings" +) //nolint:gochecknoglobals var ( @@ -52,12 +55,12 @@ func literal(s string) *regexp.Regexp { // expression defines a full expression, where each regular expression must // follow the previous. func expression(res ...*regexp.Regexp) *regexp.Regexp { - var s string + var s strings.Builder for _, re := range res { - s += re.String() + s.WriteString(re.String()) } - return match(s) + return match(s.String()) } // optional wraps the expression in a non-capturing group and makes the diff --git a/pkg/requestcontext/authn.go b/pkg/requestcontext/authn.go index 89a82ad3..512fd016 100644 --- a/pkg/requestcontext/authn.go +++ b/pkg/requestcontext/authn.go @@ -9,7 +9,7 @@ import ( // request-local context key. var amwCtxKey = Key(1) //nolint: gochecknoglobals -// pointer needed for use in context.WithValue. +// GetAuthnMiddlewareCtxKey returns a pointer needed for use in context.WithValue. func GetAuthnMiddlewareCtxKey() *Key { return &amwCtxKey } diff --git a/pkg/requestcontext/user_access_control.go b/pkg/requestcontext/user_access_control.go index c0065b3e..6c38a6c6 100644 --- a/pkg/requestcontext/user_access_control.go +++ b/pkg/requestcontext/user_access_control.go @@ -3,6 +3,7 @@ package uac import ( "context" "net/http" + "slices" glob "github.com/bmatcuk/doublestar/v4" //nolint:gci @@ -15,7 +16,7 @@ type Key int // request-local context key. var uacCtxKey = Key(0) //nolint: gochecknoglobals -// pointer needed for use in context.WithValue. +// GetContextKey returns a pointer needed for use in context.WithValue. func GetContextKey() *Key { return &uacCtxKey } @@ -116,15 +117,11 @@ func (uac *UserAccessControl) SetIsAdmin(isAdmin bool) { uac.authzInfo.isAdmin = isAdmin } -/* - UserAcFromContext returns an UserAccessControl struct made available on all http requests - (using context.Context values) by authz and authn middlewares. - - If no UserAccessControl is found on context, it will return an empty one. - -its methods and attributes can be used in http.Handlers to get user info for that specific request -(username, groups, if it's an admin, if it can access certain resources). -*/ +// UserAcFromContext returns an UserAccessControl struct made available on all http requests +// (using context.Context values) by authz and authn middlewares. +// If no UserAccessControl is found on context, it will return an empty one. +// Its methods and attributes can be used in http.Handlers to get user info for that specific request +// (username, groups, if it's an admin, if it can access certain resources). func UserAcFromContext(ctx context.Context) (*UserAccessControl, error) { if uacValue := ctx.Value(GetContextKey()); uacValue != nil { uac, ok := uacValue.(UserAccessControl) @@ -172,23 +169,11 @@ func (uac *UserAccessControl) Can(action, repository string) bool { } func (uac *UserAccessControl) isBehaviourAction(action string) bool { - for _, behaviourAction := range uac.behaviourActions { - if action == behaviourAction { - return true - } - } - - return false + return slices.Contains(uac.behaviourActions, action) } func (uac *UserAccessControl) isMethodAction(action string) bool { - for _, methodAction := range uac.methodActions { - if action == methodAction { - return true - } - } - - return false + return slices.Contains(uac.methodActions, action) } // returns whether or not glob patterns have been set in authz.go. @@ -220,22 +205,16 @@ func (uac *UserAccessControl) matchesRepo(globPatterns map[string]bool, reposito return allowed } -/* - SaveOnRequest saves UserAccessControl on the request's context. - -Later UserAcFromContext(request.Context()) can be used to obtain UserAccessControl that was saved on it. -*/ +// SaveOnRequest saves UserAccessControl on the request's context. +// Later UserAcFromContext(request.Context()) can be used to obtain UserAccessControl that was saved on it. func (uac *UserAccessControl) SaveOnRequest(request *http.Request) { uacContext := context.WithValue(request.Context(), GetContextKey(), *uac) *request = *request.WithContext(uacContext) } -/* - DeriveContext takes a context(parent) and returns a derived context(child) containing this UserAccessControl. - -Later UserAcFromContext(ctx context.Context) can be used to obtain the UserAccessControl that was added on it. -*/ +// DeriveContext takes a context(parent) and returns a derived context(child) containing this UserAccessControl. +// Later UserAcFromContext(ctx context.Context) can be used to obtain the UserAccessControl that was added on it. func (uac *UserAccessControl) DeriveContext(ctx context.Context) context.Context { return context.WithValue(ctx, GetContextKey(), *uac) } diff --git a/pkg/retention/retention.go b/pkg/retention/retention.go index bcc16f16..46fb49dd 100644 --- a/pkg/retention/retention.go +++ b/pkg/retention/retention.go @@ -3,6 +3,7 @@ package retention import ( "context" "fmt" + "slices" glob "github.com/bmatcuk/doublestar/v4" ispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -115,7 +116,7 @@ func (p policyManager) GetRetainedTagsFromIndex(ctx context.Context, repo string for _, retainCandidate := range candidates.candidates { // there may be duplicates - if !zcommon.Contains(retainTags, retainCandidate.Tag) { + if !slices.Contains(retainTags, retainCandidate.Tag) { reason := fmt.Sprintf(retainedStrFormat, retainCandidate.RetainedBy) logAction(repo, "keep", reason, retainCandidate, p.config.DryRun, &p.log) @@ -127,7 +128,7 @@ func (p policyManager) GetRetainedTagsFromIndex(ctx context.Context, repo string // log tags which will be removed for _, candidate := range candidates { - if !zcommon.Contains(retainTags, candidate.Tag) { + if !slices.Contains(retainTags, candidate.Tag) { logAction(repo, "delete", filteredByTagNames, candidate, p.config.DryRun, &p.log) if p.auditLog != nil { @@ -207,7 +208,7 @@ func (p policyManager) GetRetainedTagsFromMetaDB(ctx context.Context, repoMeta m for _, retainCandidate := range retainCandidates { // there may be duplicates - if !zcommon.Contains(retainTags, retainCandidate.Tag) { + if !slices.Contains(retainTags, retainCandidate.Tag) { // format reason log msg reason := fmt.Sprintf(retainedStrFormat, retainCandidate.RetainedBy) @@ -220,9 +221,9 @@ func (p policyManager) GetRetainedTagsFromMetaDB(ctx context.Context, repoMeta m // log tags which will be removed for _, candidateInfo := range candidates { - if !zcommon.Contains(retainTags, candidateInfo.Tag) { + if !slices.Contains(retainTags, candidateInfo.Tag) { var reason string - if zcommon.Contains(matchedByName, candidateInfo.Tag) { + if slices.Contains(matchedByName, candidateInfo.Tag) { reason = filteredByTagRules } else { reason = filteredByTagNames diff --git a/pkg/retention/rules.go b/pkg/retention/rules.go index 0be888c8..7c7e0400 100644 --- a/pkg/retention/rules.go +++ b/pkg/retention/rules.go @@ -93,10 +93,7 @@ func (lp latestPull) Perform(candidates []*types.Candidate) []*types.Candidate { }) // take top count candidates - upper := lp.count - if lp.count > len(candidates) { - upper = len(candidates) - } + upper := min(lp.count, len(candidates)) candidates = candidates[:upper] @@ -125,10 +122,7 @@ func (lp latestPush) Perform(candidates []*types.Candidate) []*types.Candidate { }) // take top count candidates - upper := lp.count - if lp.count > len(candidates) { - upper = len(candidates) - } + upper := min(lp.count, len(candidates)) candidates = candidates[:upper] diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go index 08efc18d..d0710ab7 100644 --- a/pkg/scheduler/scheduler.go +++ b/pkg/scheduler/scheduler.go @@ -167,6 +167,7 @@ func (scheduler *Scheduler) metricsWorker() { if scheduler.inShutdown() { return } + select { case <-scheduler.metricsChan: ticker.Stop() @@ -215,10 +216,7 @@ func (scheduler *Scheduler) metricsWorker() { } } -/* -Scheduler can be stopped by calling Shutdown(). -it will wait for all tasks being run to finish their work before exiting. -*/ +// Shutdown stops the scheduler. It will wait for all tasks being run to finish their work before exiting. func (scheduler *Scheduler) Shutdown() { defer scheduler.workerWg.Wait() diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go index 5fe9505d..cb011629 100644 --- a/pkg/scheduler/scheduler_test.go +++ b/pkg/scheduler/scheduler_test.go @@ -32,7 +32,7 @@ func (t *task) DoWork(ctx context.Context) error { return errInternal } - for idx := 0; idx < 5; idx++ { + for range 5 { if ctx.Err() != nil { return ctx.Err() } @@ -243,7 +243,7 @@ func TestScheduler(t *testing.T) { lastPriority := "medium" lastMediumGenerator := "1" - for _, line := range strings.Split(strings.TrimSuffix(string(data), "\n"), "\n") { + for line := range strings.SplitSeq(strings.TrimSuffix(string(data), "\n"), "\n") { if !strings.Contains(line, "priority task; index: ") { continue } diff --git a/pkg/storage/cache.go b/pkg/storage/cache.go index c1d579fa..df44c26d 100644 --- a/pkg/storage/cache.go +++ b/pkg/storage/cache.go @@ -67,7 +67,7 @@ func CreateCacheDatabaseDriver(storageConfig config.StorageConfig, log zlog.Logg return nil, nil //nolint:nilnil } -func Create(dbtype string, parameters interface{}, log zlog.Logger) (storageTypes.Cache, error) { +func Create(dbtype string, parameters any, log zlog.Logger) (storageTypes.Cache, error) { switch dbtype { case "boltdb": { diff --git a/pkg/storage/cache/boltdb.go b/pkg/storage/cache/boltdb.go index fae73c45..509ed63e 100644 --- a/pkg/storage/cache/boltdb.go +++ b/pkg/storage/cache/boltdb.go @@ -28,7 +28,7 @@ type BoltDBDriverParameters struct { UseRelPaths bool } -func NewBoltDBCache(parameters interface{}, log zlog.Logger) (*BoltDBDriver, error) { +func NewBoltDBCache(parameters any, log zlog.Logger) (*BoltDBDriver, error) { properParameters, ok := parameters.(BoltDBDriverParameters) if !ok { log.Error().Err(zerr.ErrTypeAssertionFailed).Msgf("failed to cast type, expected type '%T' but got '%T'", diff --git a/pkg/storage/cache/dynamodb.go b/pkg/storage/cache/dynamodb.go index d3111ea7..57885ec1 100644 --- a/pkg/storage/cache/dynamodb.go +++ b/pkg/storage/cache/dynamodb.go @@ -2,6 +2,7 @@ package cache import ( "context" + "slices" "strings" "github.com/aws/aws-sdk-go-v2/aws" @@ -61,7 +62,7 @@ func (d *DynamoDBDriver) NewTable(tableName string) error { return nil } -func NewDynamoDBCache(parameters interface{}, log zlog.Logger) (*DynamoDBDriver, error) { +func NewDynamoDBCache(parameters any, log zlog.Logger) (*DynamoDBDriver, error) { properParameters, ok := parameters.(DynamoDBDriverParameters) if !ok { log.Error().Err(zerr.ErrTypeAssertionFailed).Msgf("failed to cast type, expected type '%T' but got '%T'", @@ -72,7 +73,7 @@ func NewDynamoDBCache(parameters interface{}, log zlog.Logger) (*DynamoDBDriver, // custom endpoint resolver to point to localhost customResolver := aws.EndpointResolverWithOptionsFunc( //nolint: staticcheck - func(service, region string, options ...interface{}) (aws.Endpoint, error) { + func(service, region string, options ...any) (aws.Endpoint, error) { return aws.Endpoint{ //nolint: staticcheck PartitionID: "aws", URL: properParameters.Endpoint, @@ -116,7 +117,7 @@ func (d *DynamoDBDriver) Name() string { return "dynamodb" } -// Returns the original blob. +// GetBlob returns the original blob. func (d *DynamoDBDriver) GetBlob(digest godigest.Digest) (string, error) { resp, err := d.client.GetItem(context.TODO(), &dynamodb.GetItemInput{ TableName: aws.String(d.tableName), @@ -231,10 +232,8 @@ func (d *DynamoDBDriver) HasBlob(digest godigest.Digest, path string) bool { return true } - for _, item := range out.DuplicateBlobPath { - if item == path { - return true - } + if slices.Contains(out.DuplicateBlobPath, path) { + return true } d.log.Debug().Err(zerr.ErrCacheMiss).Str("digest", string(digest)).Msg("failed to find blob in cache") @@ -243,7 +242,7 @@ func (d *DynamoDBDriver) HasBlob(digest godigest.Digest, path string) bool { } func (d *DynamoDBDriver) DeleteBlob(digest godigest.Digest, path string) error { - marshaledKey, _ := attributevalue.MarshalMap(map[string]interface{}{"Digest": digest.String()}) + marshaledKey, _ := attributevalue.MarshalMap(map[string]any{"Digest": digest.String()}) expression := "DELETE DuplicateBlobPath :i" attrPath := types.AttributeValueMemberSS{Value: []string{path}} @@ -322,7 +321,7 @@ func (d *DynamoDBDriver) putOriginBlob(digest godigest.Digest, path string) erro func (d *DynamoDBDriver) updateItem(digest godigest.Digest, expression string, expressionAttVals map[string]types.AttributeValue, ) error { - marshaledKey, _ := attributevalue.MarshalMap(map[string]interface{}{"Digest": digest.String()}) + marshaledKey, _ := attributevalue.MarshalMap(map[string]any{"Digest": digest.String()}) _, err := d.client.UpdateItem(context.TODO(), &dynamodb.UpdateItemInput{ Key: marshaledKey, diff --git a/pkg/storage/cache/redis.go b/pkg/storage/cache/redis.go index bc777e5c..112da2cc 100644 --- a/pkg/storage/cache/redis.go +++ b/pkg/storage/cache/redis.go @@ -32,7 +32,7 @@ type RedisDriverParameters struct { KeyPrefix string } -func NewRedisCache(parameters interface{}, log zlog.Logger) (*RedisDriver, error) { +func NewRedisCache(parameters any, log zlog.Logger) (*RedisDriver, error) { properParameters, ok := parameters.(RedisDriverParameters) if !ok { log.Error().Err(zerr.ErrTypeAssertionFailed).Msgf("failed to cast type, expected type '%T' but got '%T'", diff --git a/pkg/storage/cache_benchmark_test.go b/pkg/storage/cache_benchmark_test.go index 5d295410..46a51312 100644 --- a/pkg/storage/cache_benchmark_test.go +++ b/pkg/storage/cache_benchmark_test.go @@ -3,6 +3,7 @@ package storage_test import ( "math/rand" "os/exec" + "strings" "testing" "time" @@ -27,16 +28,21 @@ func generateData() map[godigest.Digest]string { //nolint: gosec seededRand := rand.New(rand.NewSource(time.Now().UnixNano())) - for i := 0; i < datasetSize; i++ { + for range datasetSize { randomString, _ := test.GenerateRandomString() counter := 0 + var randomStringBuilder strings.Builder + randomStringBuilder.WriteString(randomString) + for seededRand.Float32() < 0.5 && counter < 5 { counter++ - randomString += "/" + + randomStringBuilder.WriteString("/") rs, _ := test.GenerateRandomString() - randomString += rs + randomStringBuilder.WriteString(rs) } + randomString = randomStringBuilder.String() digest := godigest.FromString(randomString) dataMap[digest] = randomString @@ -71,7 +77,7 @@ func helperGetAll(cache storageTypes.Cache, testData map[godigest.Digest]string) func helperMix(cache storageTypes.Cache, testData map[godigest.Digest]string, digestSlice []godigest.Digest) { // The test data contains datasetSize entries by default, and each set of operations uses 5 entries - for i := 0; i < 1000; i++ { + for i := range 1000 { _ = cache.PutBlob(digestSlice[i*5], testData[digestSlice[i*5]]) _ = cache.PutBlob(digestSlice[i*5+1], testData[digestSlice[i*5+1]]) _ = cache.PutBlob(digestSlice[i*5+2], testData[digestSlice[i*5+2]]) @@ -204,7 +210,8 @@ func BenchmarkPutLocalstack(b *testing.B) { log.Info().Int64("seed", seed).Msg("random seed for tableName") // Create Table - _, err := exec.Command("aws", "dynamodb", "--region", region, "--endpoint-url", localEndpoint, "create-table", + _, err := exec.Command( //nolint: noctx + "aws", "dynamodb", "--region", region, "--endpoint-url", localEndpoint, "create-table", "--table-name", tableName, "--attribute-definitions", "AttributeName=Digest,AttributeType=S", "--key-schema", "AttributeName=Digest,KeyType=HASH", "--billing-mode", "PAY_PER_REQUEST").Output() @@ -230,7 +237,8 @@ func BenchmarkDeleteLocalstack(b *testing.B) { log.Info().Int64("seed", seed).Msg("random seed for tableName") // Create Table - _, err := exec.Command("aws", "dynamodb", "--region", region, "--endpoint-url", localEndpoint, "create-table", + _, err := exec.Command( //nolint: noctx + "aws", "dynamodb", "--region", region, "--endpoint-url", localEndpoint, "create-table", "--table-name", tableName, "--attribute-definitions", "AttributeName=Digest,AttributeType=S", "--key-schema", "AttributeName=Digest,KeyType=HASH", "--billing-mode", "PAY_PER_REQUEST").Output() @@ -260,7 +268,8 @@ func BenchmarkHasLocalstack(b *testing.B) { log.Info().Int64("seed", seed).Msg("random seed for tableName") // Create Table - _, err := exec.Command("aws", "dynamodb", "--region", region, "--endpoint-url", localEndpoint, "create-table", + _, err := exec.Command( //nolint: noctx + "aws", "dynamodb", "--region", region, "--endpoint-url", localEndpoint, "create-table", "--table-name", tableName, "--attribute-definitions", "AttributeName=Digest,AttributeType=S", "--key-schema", "AttributeName=Digest,KeyType=HASH", "--billing-mode", "PAY_PER_REQUEST").Output() @@ -290,7 +299,8 @@ func BenchmarkGetLocalstack(b *testing.B) { log.Info().Int64("seed", seed).Msg("random seed for tableName") // Create Table - _, err := exec.Command("aws", "dynamodb", "--region", region, "--endpoint-url", localEndpoint, "create-table", + _, err := exec.Command( //nolint: noctx + "aws", "dynamodb", "--region", region, "--endpoint-url", localEndpoint, "create-table", "--table-name", tableName, "--attribute-definitions", "AttributeName=Digest,AttributeType=S", "--key-schema", "AttributeName=Digest,KeyType=HASH", "--billing-mode", "PAY_PER_REQUEST").Output() @@ -330,7 +340,8 @@ func BenchmarkMixLocalstack(b *testing.B) { log.Info().Int64("seed", seed).Msg("random seed for tableName") // Create Table - _, err := exec.Command("aws", "dynamodb", "--region", region, "--endpoint-url", localEndpoint, "create-table", + _, err := exec.Command( //nolint: noctx + "aws", "dynamodb", "--region", region, "--endpoint-url", localEndpoint, "create-table", "--table-name", tableName, "--attribute-definitions", "AttributeName=Digest,AttributeType=S", "--key-schema", "AttributeName=Digest,KeyType=HASH", "--billing-mode", "PAY_PER_REQUEST").Output() @@ -367,7 +378,8 @@ func BenchmarkPutAWS(b *testing.B) { log.Info().Int64("seed", seed).Msg("random seed for tableName") // Create Table - _, err := exec.Command("aws", "dynamodb", "--region", region, "--endpoint-url", awsEndpoint, "create-table", + _, err := exec.Command( //nolint: noctx + "aws", "dynamodb", "--region", region, "--endpoint-url", awsEndpoint, "create-table", "--table-name", tableName, "--attribute-definitions", "AttributeName=Digest,AttributeType=S", "--key-schema", "AttributeName=Digest,KeyType=HASH", "--billing-mode", "PAY_PER_REQUEST").Output() @@ -393,7 +405,8 @@ func BenchmarkDeleteAWS(b *testing.B) { log.Info().Int64("seed", seed).Msg("random seed for tableName") // Create Table - _, err := exec.Command("aws", "dynamodb", "--region", region, "--endpoint-url", awsEndpoint, "create-table", + _, err := exec.Command( //nolint: noctx + "aws", "dynamodb", "--region", region, "--endpoint-url", awsEndpoint, "create-table", "--table-name", tableName, "--attribute-definitions", "AttributeName=Digest,AttributeType=S", "--key-schema", "AttributeName=Digest,KeyType=HASH", "--billing-mode", "PAY_PER_REQUEST").Output() @@ -423,7 +436,8 @@ func BenchmarkHasAWS(b *testing.B) { log.Info().Int64("seed", seed).Msg("random seed for tableName") // Create Table - _, err := exec.Command("aws", "dynamodb", "--region", region, "--endpoint-url", awsEndpoint, "create-table", + _, err := exec.Command( //nolint: noctx + "aws", "dynamodb", "--region", region, "--endpoint-url", awsEndpoint, "create-table", "--table-name", tableName, "--attribute-definitions", "AttributeName=Digest,AttributeType=S", "--key-schema", "AttributeName=Digest,KeyType=HASH", "--billing-mode", "PAY_PER_REQUEST").Output() @@ -453,7 +467,8 @@ func BenchmarkGetAWS(b *testing.B) { log.Info().Int64("seed", seed).Msg("random seed for tableName") // Create Table - _, err := exec.Command("aws", "dynamodb", "--region", region, "--endpoint-url", awsEndpoint, "create-table", + _, err := exec.Command( //nolint: noctx + "aws", "dynamodb", "--region", region, "--endpoint-url", awsEndpoint, "create-table", "--table-name", tableName, "--attribute-definitions", "AttributeName=Digest,AttributeType=S", "--key-schema", "AttributeName=Digest,KeyType=HASH", "--billing-mode", "PAY_PER_REQUEST").Output() @@ -493,7 +508,8 @@ func BenchmarkMixAWS(b *testing.B) { log.Info().Int64("seed", seed).Msg("random seed for tableName") // Create Table - _, err := exec.Command("aws", "dynamodb", "--region", region, "--endpoint-url", awsEndpoint, "create-table", + _, err := exec.Command( //nolint: noctx + "aws", "dynamodb", "--region", region, "--endpoint-url", awsEndpoint, "create-table", "--table-name", tableName, "--attribute-definitions", "AttributeName=Digest,AttributeType=S", "--key-schema", "AttributeName=Digest,KeyType=HASH", "--billing-mode", "PAY_PER_REQUEST").Output() diff --git a/pkg/storage/cache_test.go b/pkg/storage/cache_test.go index 44ec458c..9daa9e13 100644 --- a/pkg/storage/cache_test.go +++ b/pkg/storage/cache_test.go @@ -77,7 +77,7 @@ func TestCache(t *testing.T) { log := log.NewTestLogger() So(log, ShouldNotBeNil) - cacheDriver, err := storage.Create("sometype", map[string]interface{}{}, log) + cacheDriver, err := storage.Create("sometype", map[string]any{}, log) So(err, ShouldEqual, errors.ErrBadConfig) So(cacheDriver, ShouldBeNil) }) diff --git a/pkg/storage/common/common.go b/pkg/storage/common/common.go index 571da481..4f751aaa 100644 --- a/pkg/storage/common/common.go +++ b/pkg/storage/common/common.go @@ -8,6 +8,7 @@ import ( "fmt" "math/rand" "path" + "slices" "strings" "time" @@ -174,7 +175,7 @@ func ValidateManifest(imgStore storageTypes.ImageStore, repo, reference, mediaTy return nil } -// Returns the canonical digest or the digest provided by the reference if any +// GetAndValidateRequestDigest returns the canonical digest or the digest provided by the reference if any. // Per spec, the canonical digest would always be returned to the client in // request headers, but that does not make sense if the client requested a different digest algorithm // See https://github.com/opencontainers/distribution-spec/issues/494 @@ -221,7 +222,6 @@ func CheckIfIndexNeedsUpdate(index *ispec.Index, desc *ispec.Descriptor, updateIndex := true for midx, manifest := range index.Manifests { - manifest := manifest if reference == manifest.Digest.String() { // nothing changed, so don't update updateIndex = false @@ -398,11 +398,9 @@ func RemoveManifestDescByReference(index *ispec.Index, reference string, detectC return removedManifest, nil } -/* -Unmarshal an image index and for all manifests in that -index, ensure that they do not have a name or they are not in other -manifest indexes else GC can never clean them. -*/ +// UpdateIndexWithPrunedImageManifests unmarshals an image index and for all manifests in that +// index, ensures that they do not have a name or they are not in other +// manifest indexes else GC can never clean them. func UpdateIndexWithPrunedImageManifests(imgStore storageTypes.ImageStore, index *ispec.Index, repo string, desc ispec.Descriptor, oldDgst godigest.Digest, log zlog.Logger, ) error { @@ -428,14 +426,11 @@ func UpdateIndexWithPrunedImageManifests(imgStore storageTypes.ImageStore, index return nil } -/* -Before an image index manifest is pushed to a repo, its constituent manifests -are pushed first, so when updating/removing this image index manifest, we also -need to determine if there are other image index manifests which refer to the -same constitutent manifests so that they can be garbage-collected correctly - -PruneImageManifestsFromIndex is a helper routine to achieve this. -*/ +// PruneImageManifestsFromIndex is a helper routine that prunes image manifests from an index. +// Before an image index manifest is pushed to a repo, its constituent manifests +// are pushed first, so when updating/removing this image index manifest, we also +// need to determine if there are other image index manifests which refer to the +// same constitutent manifests so that they can be garbage-collected correctly. func PruneImageManifestsFromIndex(imgStore storageTypes.ImageStore, repo string, digest godigest.Digest, //nolint:gocyclo,lll outIndex ispec.Index, otherImgIndexes []ispec.Descriptor, log zlog.Logger, ) ([]ispec.Descriptor, error) { @@ -736,7 +731,7 @@ func GetReferrers(imgStore storageTypes.ImageStore, repo string, gdigest godiges // filter by artifact type manifestArtifactType := zcommon.GetManifestArtifactType(manifestContent) - if len(artifactTypes) > 0 && !zcommon.Contains(artifactTypes, manifestArtifactType) { + if len(artifactTypes) > 0 && !slices.Contains(artifactTypes, manifestArtifactType) { continue } @@ -762,7 +757,7 @@ func GetReferrers(imgStore storageTypes.ImageStore, repo string, gdigest godiges indexArtifactType := zcommon.GetIndexArtifactType(indexContent) - if len(artifactTypes) > 0 && !zcommon.Contains(artifactTypes, indexArtifactType) { + if len(artifactTypes) > 0 && !slices.Contains(artifactTypes, indexArtifactType) { continue } @@ -786,7 +781,8 @@ func GetReferrers(imgStore storageTypes.ImageStore, repo string, gdigest godiges return index, nil } -// Get blob descriptor from it's manifest contents, if blob can not be found it will return error. +// GetBlobDescriptorFromRepo gets blob descriptor from it's manifest contents, +// if blob can not be found it will return error. func GetBlobDescriptorFromRepo(imgStore storageTypes.ImageStore, repo string, blobDigest godigest.Digest, log zlog.Logger, ) (ispec.Descriptor, error) { @@ -906,12 +902,9 @@ func IsEmptyLayersError(err error) bool { return false } -/* - DedupeTaskGenerator takes all blobs paths found in the storage.imagestore and groups them by digest - -for each digest and based on the dedupe value it will dedupe or restore deduped blobs to the original state(undeduped)\ -by creating a task for each digest and pushing it to the task scheduler. -*/ +// DedupeTaskGenerator takes all blobs paths found in the storage.imagestore and groups them by digest. +// For each digest and based on the dedupe value it will dedupe or restore deduped blobs +// to the original state(undeduped) by creating a task for each digest and pushing it to the task scheduler. type DedupeTaskGenerator struct { ImgStore storageTypes.ImageStore // storage dedupe value diff --git a/pkg/storage/gc/gc.go b/pkg/storage/gc/gc.go index ddcc1068..47c6a0d0 100644 --- a/pkg/storage/gc/gc.go +++ b/pkg/storage/gc/gc.go @@ -6,6 +6,7 @@ import ( "fmt" "math/rand" "path" + "slices" "strconv" "strings" "time" @@ -418,7 +419,7 @@ func (gc GarbageCollect) removeTagsPerRetentionPolicy(ctx context.Context, repo // check tag tag, ok := getDescriptorTag(desc) - if ok && !zcommon.Contains(retainTags, tag) { + if ok && !slices.Contains(retainTags, tag) { // remove tags which should not be retained _, err := gc.removeManifest(repo, index, desc, tag, "", "") if err != nil && !errors.Is(err, zerr.ErrManifestNotFound) { @@ -859,12 +860,9 @@ func getDescriptorTag(desc ispec.Descriptor) (string, bool) { return tag, ok } -/* - GCTaskGenerator takes all repositories found in the storage.imagestore - -and it will execute garbage collection for each repository by creating a task -for each repository and pushing it to the task scheduler. -*/ +// GCTaskGenerator takes all repositories found in the storage.imagestore +// and it will execute garbage collection for each repository by creating a task +// for each repository and pushing it to the task scheduler. type GCTaskGenerator struct { imgStore types.ImageStore gc GarbageCollect diff --git a/pkg/storage/gc/gc_test.go b/pkg/storage/gc/gc_test.go index bb2ddc85..db722794 100644 --- a/pkg/storage/gc/gc_test.go +++ b/pkg/storage/gc/gc_test.go @@ -68,7 +68,6 @@ func TestGarbageCollectAndRetentionMetaDB(t *testing.T) { trueVal := true for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var imgStore storageTypes.ImageStore @@ -89,7 +88,7 @@ func TestGarbageCollectAndRetentionMetaDB(t *testing.T) { bucket := "zot-storage-test" - storageDriverParams := map[string]interface{}{ + storageDriverParams := map[string]any{ "rootDir": rootDir, "name": "s3", "region": region, @@ -1762,7 +1761,6 @@ func TestGarbageCollectAndRetentionNoMetaDB(t *testing.T) { trueVal := true for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var imgStore storageTypes.ImageStore @@ -1783,7 +1781,7 @@ func TestGarbageCollectAndRetentionNoMetaDB(t *testing.T) { bucket := "zot-storage-test" - storageDriverParams := map[string]interface{}{ + storageDriverParams := map[string]any{ "rootDir": rootDir, "name": "s3", "region": region, @@ -2197,13 +2195,12 @@ func TestGarbageCollectAndRetentionNoMetaDB(t *testing.T) { t.Logf("index %d, repo '%s'", i, repo) So(err, ShouldBeNil) - if i >= 5 { + if i >= len(expectedRepos) { So(repo, ShouldEqual, "") continue - } else { - So(repo, ShouldEqual, expectedRepos[i]) } + So(repo, ShouldEqual, expectedRepos[i]) processedRepos[repo] = struct{}{} diff --git a/pkg/storage/imagestore/imagestore.go b/pkg/storage/imagestore/imagestore.go index 622626e5..ff16558a 100644 --- a/pkg/storage/imagestore/imagestore.go +++ b/pkg/storage/imagestore/imagestore.go @@ -9,6 +9,7 @@ import ( "io" "path" "path/filepath" + "slices" "strings" "sync" "time" @@ -1315,11 +1316,8 @@ func (is *ImageStore) GetAllDedupeReposCandidates(digest godigest.Digest) ([]str return repos, nil } -/* - CheckBlob verifies a blob and returns true if the blob is correct - -If the blob is not found but it's found in cache then it will be copied over. -*/ +// CheckBlob verifies a blob and returns true if the blob is correct. +// If the blob is not found but it's found in cache then it will be copied over. func (is *ImageStore) CheckBlob(repo string, digest godigest.Digest) (bool, int64, error) { var lockLatency time.Time @@ -1918,7 +1916,7 @@ func (is *ImageStore) GetNextDigestWithBlobPaths(repos []string, lastDigests []g if fileInfo.IsDir() { // skip repositories not found in repos baseName := path.Base(fileInfo.Path()) - if zcommon.Contains(repos, baseName) || baseName == ispec.ImageBlobsDir { + if slices.Contains(repos, baseName) || baseName == ispec.ImageBlobsDir { return nil } @@ -1934,7 +1932,7 @@ func (is *ImageStore) GetNextDigestWithBlobPaths(repos []string, lastDigests []g baseName := path.Base(fileInfo.Path()) skippedFiles := []string{ispec.ImageLayoutFile, ispec.ImageIndexFile, "meta.db", "cache.db"} - if zcommon.Contains(skippedFiles, baseName) { + if slices.Contains(skippedFiles, baseName) { return nil } @@ -1950,7 +1948,7 @@ func (is *ImageStore) GetNextDigestWithBlobPaths(repos []string, lastDigests []g return nil //nolint: nilerr // ignore files which are not blobs } - if digest == "" && !zcommon.Contains(lastDigests, blobDigest) { + if digest == "" && !slices.Contains(lastDigests, blobDigest) { digest = blobDigest } diff --git a/pkg/storage/local/driver.go b/pkg/storage/local/driver.go index 07adf274..0afdc1b3 100644 --- a/pkg/storage/local/driver.go +++ b/pkg/storage/local/driver.go @@ -319,6 +319,7 @@ func (driver *Driver) formatErr(err error) error { type fileInfo struct { os.FileInfo + path string } diff --git a/pkg/storage/local/driver_test.go b/pkg/storage/local/driver_test.go index 5b97ec4d..b6e19304 100644 --- a/pkg/storage/local/driver_test.go +++ b/pkg/storage/local/driver_test.go @@ -700,6 +700,7 @@ var ( // mockFile implements FileInterface for testing sync behavior. type mockFile struct { *os.File + syncCalled bool syncError error closeError error diff --git a/pkg/storage/local/local_elevated_test.go b/pkg/storage/local/local_elevated_test.go index 27ed05f4..f3253cc5 100644 --- a/pkg/storage/local/local_elevated_test.go +++ b/pkg/storage/local/local_elevated_test.go @@ -1,5 +1,4 @@ //go:build needprivileges -// +build needprivileges package local_test @@ -81,6 +80,7 @@ func TestElevatedPrivilegesInvalidDedupe(t *testing.T) { So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + //nolint: noctx // old code, no context available cmd := exec.Command("chattr", "+i", path.Join(dir, "dedupe2", "blobs/sha256", blobDigest1)) //nolint: gosec _, err = cmd.Output() @@ -92,6 +92,7 @@ func TestElevatedPrivilegesInvalidDedupe(t *testing.T) { So(err, ShouldNotBeNil) So(blob, ShouldEqual, buflen) + //nolint: noctx // old code, no context available cmd = exec.Command("chattr", "-i", path.Join(dir, "dedupe2", "blobs/sha256", blobDigest1)) //nolint: gosec _, err = cmd.Output() diff --git a/pkg/storage/local/local_test.go b/pkg/storage/local/local_test.go index 4147f8a4..1708fdf7 100644 --- a/pkg/storage/local/local_test.go +++ b/pkg/storage/local/local_test.go @@ -1297,7 +1297,7 @@ func TestDedupeLinks(t *testing.T) { }) Convey("Intrerrupt rebuilding and restart, checking idempotency", func() { - for i := 0; i < 10; i++ { + for i := range 10 { taskScheduler := runAndGetScheduler() defer taskScheduler.Shutdown() @@ -1860,7 +1860,7 @@ func TestNegativeCases(t *testing.T) { Convey("DirExists call with name too long as argument", t, func(c C) { var builder strings.Builder - for i := 0; i < 1025; i++ { + for range 1025 { _, err := builder.WriteString("0") if err != nil { t.Fatal(err) @@ -2444,7 +2444,7 @@ func TestGarbageCollectErrors(t *testing.T) { index.SchemaVersion = 2 index.MediaType = ispec.MediaTypeImageIndex - for i := 0; i < 4; i++ { + for range 4 { // upload image config blob upload, err = imgStore.NewBlobUpload(repoName) So(err, ShouldBeNil) diff --git a/pkg/storage/s3/driver.go b/pkg/storage/s3/driver.go index 87663c65..fc51684a 100644 --- a/pkg/storage/s3/driver.go +++ b/pkg/storage/s3/driver.go @@ -104,12 +104,9 @@ func (driver *Driver) SameFile(path1, path2 string) bool { return false } -/* - Link put an empty file that will act like a link between the original file and deduped one - -because s3 doesn't support symlinks, wherever the storage will encounter an empty file, it will get the original one -from cache. -*/ +// Link puts an empty file that will act like a link between the original file and deduped one. +// Because s3 doesn't support symlinks, wherever the storage will encounter an empty file, it will get the original one +// from cache. func (driver *Driver) Link(src, dest string) error { return driver.store.PutContent(context.Background(), dest, []byte{}) } diff --git a/pkg/storage/s3/s3.go b/pkg/storage/s3/s3.go index 3d49f0f5..89a4c50d 100644 --- a/pkg/storage/s3/s3.go +++ b/pkg/storage/s3/s3.go @@ -15,7 +15,7 @@ import ( storageTypes "zotregistry.dev/zot/v2/pkg/storage/types" ) -// NewObjectStorage returns a new image store backed by cloud storages. +// NewImageStore returns a new image store backed by cloud storages. // see https://github.com/docker/docker.github.io/tree/master/registry/storage-drivers // Use the last argument to properly set a cache database, or it will default to boltDB local storage. func NewImageStore(rootDir string, cacheDir string, dedupe, commit bool, log zlog.Logger, diff --git a/pkg/storage/s3/s3_test.go b/pkg/storage/s3/s3_test.go index b75b68c0..62a0d67f 100644 --- a/pkg/storage/s3/s3_test.go +++ b/pkg/storage/s3/s3_test.go @@ -93,7 +93,7 @@ func createMockStorageWithMockCache(rootDir string, dedupe bool, store driver.St func createStoreDriver(rootDir string) driver.StorageDriver { bucket := zotStorageTest endpoint := os.Getenv("S3MOCK_ENDPOINT") - storageDriverParams := map[string]interface{}{ + storageDriverParams := map[string]any{ "rootDir": rootDir, "name": "s3", "region": s3Region, @@ -368,7 +368,7 @@ func (s *StorageDriverMock) Delete(ctx context.Context, path string) error { return nil } -func (s *StorageDriverMock) URLFor(ctx context.Context, path string, options map[string]interface{}) (string, error) { +func (s *StorageDriverMock) URLFor(ctx context.Context, path string, options map[string]any) (string, error) { return "", nil } @@ -683,7 +683,7 @@ func TestNegativeCasesObjectsStorage(t *testing.T) { "/a": { Dedupe: true, RootDirectory: t.TempDir(), - StorageDriver: map[string]interface{}{ + StorageDriver: map[string]any{ "rootDir": "/a", "name": "s3", "region": s3Region, @@ -2018,7 +2018,7 @@ func TestRebuildDedupeIndex(t *testing.T) { So(configFi2.Size(), ShouldEqual, 0) Convey("Intrerrupt rebuilding and restart, checking idempotency", func() { - for i := 0; i < 10; i++ { + for i := range 10 { log := log.NewTestLogger() metrics := monitoring.NewMetricsServer(false, log) taskScheduler := scheduler.NewScheduler(config.New(), metrics, log) @@ -2060,7 +2060,7 @@ func TestRebuildDedupeIndex(t *testing.T) { So(configFi2.Size(), ShouldEqual, configFi1.Size()) // now from dedupe false to true - for i := 0; i < 10; i++ { + for i := range 10 { log := log.NewTestLogger() metrics := monitoring.NewMetricsServer(false, log) taskScheduler := scheduler.NewScheduler(config.New(), metrics, log) diff --git a/pkg/storage/scrub.go b/pkg/storage/scrub.go index fb4a6921..ef8bfe62 100644 --- a/pkg/storage/scrub.go +++ b/pkg/storage/scrub.go @@ -26,7 +26,9 @@ const ( colStatusIndex colAffectedBlobIndex colErrorIndex +) +const ( imageNameWidth = 32 tagWidth = 24 statusWidth = 8 diff --git a/pkg/storage/scrub_test.go b/pkg/storage/scrub_test.go index 617e85cd..ee7f977e 100644 --- a/pkg/storage/scrub_test.go +++ b/pkg/storage/scrub_test.go @@ -68,7 +68,7 @@ func TestRedisCheckAllBlobsIntegrity(t *testing.T) { metrics := monitoring.NewMetricsServer(false, log) - client, _ := rediscfg.GetRedisClient(map[string]interface{}{"url": "redis://" + miniRedis.Addr()}, log) + client, _ := rediscfg.GetRedisClient(map[string]any{"url": "redis://" + miniRedis.Addr()}, log) cacheDriver, _ := storage.Create("redis", cache.RedisDriverParameters{ Client: client, diff --git a/pkg/storage/storage_test.go b/pkg/storage/storage_test.go index 2c1eccef..1c20e186 100644 --- a/pkg/storage/storage_test.go +++ b/pkg/storage/storage_test.go @@ -87,7 +87,7 @@ func createObjectsStore(options createObjectStoreOpts) ( } if options.cacheType == storageConstants.RedisDriverName { - client, _ := rediscfg.GetRedisClient(map[string]interface{}{"url": options.miniRedisAddr}, log) + client, _ := rediscfg.GetRedisClient(map[string]any{"url": options.miniRedisAddr}, log) cacheDriver, _ = storage.Create("redis", cache.RedisDriverParameters{ Client: client, @@ -115,7 +115,7 @@ func createObjectsStore(options createObjectStoreOpts) ( bucket := "zot-storage-test" endpoint := os.Getenv("S3MOCK_ENDPOINT") - storageDriverParams := map[string]interface{}{ + storageDriverParams := map[string]any{ "rootDir": options.rootDir, "name": "s3", "region": "us-east-2", @@ -180,7 +180,7 @@ func TestStorageNew(t *testing.T) { // store name is wrong conf := config.New() conf.Storage.RootDirectory = "dir" - conf.Storage.StorageDriver = map[string]interface{}{} + conf.Storage.StorageDriver = map[string]any{} _, err := storage.New(conf, nil, nil, zlog.NewTestLogger(), nil) So(err, ShouldNotBeNil) @@ -189,7 +189,6 @@ func TestStorageNew(t *testing.T) { func TestGetAllDedupeReposCandidates(t *testing.T) { for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var imgStore storageTypes.ImageStore @@ -262,7 +261,6 @@ func TestGetAllDedupeReposCandidates(t *testing.T) { func TestStorageAPIs(t *testing.T) { for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var imgStore storageTypes.ImageStore @@ -975,7 +973,7 @@ func TestStorageAPIs(t *testing.T) { Convey("Locks", func() { // in parallel, a mix of read and write locks - mainly for coverage var wg sync.WaitGroup - for i := 0; i < 1000; i++ { + for range 1000 { wg.Add(2) go func() { @@ -1005,7 +1003,6 @@ func TestStorageAPIs(t *testing.T) { func TestMandatoryAnnotations(t *testing.T) { for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var ( imgStore storageTypes.ImageStore @@ -1163,7 +1160,7 @@ func TestStorageSubpaths(t *testing.T) { "a/": { RootDirectory: tmpDirSubpath, RemoteCache: true, - StorageDriver: map[string]interface{}{}, + StorageDriver: map[string]any{}, Dedupe: true, }, }, @@ -1191,7 +1188,7 @@ func TestStorageSubpaths(t *testing.T) { "a/": { RootDirectory: tmpDirSubpath, RemoteCache: true, - StorageDriver: map[string]interface{}{ + StorageDriver: map[string]any{ "name": "bad-name", }, }, @@ -1206,7 +1203,6 @@ func TestStorageSubpaths(t *testing.T) { func TestDeleteBlobsInUse(t *testing.T) { for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var imgStore storageTypes.ImageStore @@ -1379,7 +1375,7 @@ func TestDeleteBlobsInUse(t *testing.T) { var cblob []byte //nolint: dupl - for i := 0; i < 4; i++ { + for range 4 { // upload image config blob upload, err = imgStore.NewBlobUpload(repoName) So(err, ShouldBeNil) @@ -1515,7 +1511,6 @@ func TestDeleteBlobsInUse(t *testing.T) { func TestReuploadCorruptedBlob(t *testing.T) { for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var ( imgStore storageTypes.ImageStore @@ -1650,7 +1645,6 @@ func TestReuploadCorruptedBlob(t *testing.T) { func TestStorageHandler(t *testing.T) { for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var ( firstStore storageTypes.ImageStore @@ -1764,7 +1758,6 @@ func TestRoutePrefix(t *testing.T) { func TestGarbageCollectImageManifest(t *testing.T) { for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { log := zlog.NewTestLogger() audit := zlog.NewAuditLogger("debug", "") @@ -2448,7 +2441,6 @@ func TestGarbageCollectImageManifest(t *testing.T) { func TestGarbageCollectImageIndex(t *testing.T) { for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { log := zlog.NewTestLogger() audit := zlog.NewAuditLogger("debug", "") @@ -2856,7 +2848,6 @@ func TestGarbageCollectImageIndex(t *testing.T) { func TestGarbageCollectChainedImageIndexes(t *testing.T) { for _, testcase := range testCases { - testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { log := zlog.NewTestLogger() audit := zlog.NewAuditLogger("debug", "") @@ -2960,7 +2951,7 @@ func TestGarbageCollectChainedImageIndexes(t *testing.T) { var digest godigest.Digest - for i := 0; i < 4; i++ { //nolint: dupl + for range 4 { //nolint: dupl // upload image config blob upload, err := imgStore.NewBlobUpload(repoName) So(err, ShouldBeNil) @@ -3043,7 +3034,7 @@ func TestGarbageCollectChainedImageIndexes(t *testing.T) { innerIndex.SchemaVersion = 2 innerIndex.MediaType = ispec.MediaTypeImageIndex - for i := 0; i < 3; i++ { //nolint: dupl + for range 3 { //nolint: dupl // upload image config blob upload, err := imgStore.NewBlobUpload(repoName) So(err, ShouldBeNil) @@ -3349,7 +3340,7 @@ func pushRandomImageIndex(imgStore storageTypes.ImageStore, repoName string, var digest godigest.Digest - for i := 0; i < 4; i++ { //nolint: dupl + for range 4 { //nolint: dupl // upload image config blob upload, err := imgStore.NewBlobUpload(repoName) So(err, ShouldBeNil) diff --git a/pkg/test/auth/bearer.go b/pkg/test/auth/bearer.go index 2ddc3d1b..8746ded8 100644 --- a/pkg/test/auth/bearer.go +++ b/pkg/test/auth/bearer.go @@ -147,7 +147,7 @@ func ParseBearerAuthHeader(authHeaderRaw string) *AuthHeader { matches := re.FindAllStringSubmatch(authHeaderRaw, -1) matchmap := make(map[string]string) - for i := 0; i < len(matches); i++ { + for i := range matches { matchmap[matches[i][1]] = matches[i][2] } diff --git a/pkg/test/auth/oidc.go b/pkg/test/auth/oidc.go index f652617e..134b5cbf 100644 --- a/pkg/test/auth/oidc.go +++ b/pkg/test/auth/oidc.go @@ -18,7 +18,7 @@ func MockOIDCRun() (*mockoidc.MockOIDC, error) { mockServer, _ := mockoidc.NewServer(rsaKey) // Create the net.Listener, kernel will chose a valid port - listener, _ := net.Listen("tcp", "127.0.0.1:0") + listener, _ := net.Listen("tcp", "127.0.0.1:0") //nolint: noctx bearerMiddleware := func(next http.Handler) http.Handler { return http.HandlerFunc(func(response http.ResponseWriter, req *http.Request) { diff --git a/pkg/test/common/fs_test.go b/pkg/test/common/fs_test.go index 765e4ad2..991913c1 100644 --- a/pkg/test/common/fs_test.go +++ b/pkg/test/common/fs_test.go @@ -273,7 +273,7 @@ func TestGetBcryptCredString(t *testing.T) { passwordSize := 100 pass := make([]byte, passwordSize) - for i := 0; i < passwordSize; i++ { + for i := range passwordSize { pass[i] = 'Y' } diff --git a/pkg/test/common/utils.go b/pkg/test/common/utils.go index 5f9ff390..f92a380b 100644 --- a/pkg/test/common/utils.go +++ b/pkg/test/common/utils.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "maps" "math/rand" "net/http" "net/url" @@ -178,9 +179,7 @@ func CustomRedirectPolicy(noOfRedirect int) resty.RedirectPolicy { return fmt.Errorf("stopped after %d redirects", noOfRedirect) //nolint: err113 } - for key, val := range via[len(via)-1].Header { - req.Header[key] = val - } + maps.Copy(req.Header, via[len(via)-1].Header) respCookies := req.Response.Cookies() for _, cookie := range respCookies { @@ -191,7 +190,7 @@ func CustomRedirectPolicy(noOfRedirect int) resty.RedirectPolicy { }) } -// Generates a random string with length 10 from lower case & upper case characters and +// GenerateRandomString generates a random string with length 10 from lower case & upper case characters and // a seed that can be logged in tests (if test fails, you can reconstruct random string). func GenerateRandomString() (string, int64) { seed := time.Now().UnixNano() @@ -207,7 +206,7 @@ func GenerateRandomString() (string, int64) { return string(randomBytes), seed } -// Generates a random string with length 10 from lower case characters and digits and +// GenerateRandomName generates a random string with length 10 from lower case characters and digits and // a seed that can be logged in tests (if test fails, you can reconstruct random string). func GenerateRandomName() (string, int64) { seed := time.Now().UnixNano() diff --git a/pkg/test/common/utils_test.go b/pkg/test/common/utils_test.go index f90558db..f805ed7d 100644 --- a/pkg/test/common/utils_test.go +++ b/pkg/test/common/utils_test.go @@ -16,6 +16,7 @@ import ( func TestWaitTillTrivyDBDownloadStarted(t *testing.T) { Convey("finishes successfully", t, func() { tempDir := t.TempDir() + go func() { tcommon.WaitTillTrivyDBDownloadStarted(tempDir) }() @@ -149,7 +150,7 @@ func TestWaitForLogMessages(t *testing.T) { // Simulate concurrent writes go func() { - for i := 0; i < 5; i++ { + for range 5 { _, _ = logBuffer.Write([]byte("Starting server\n")) time.Sleep(5 * time.Millisecond) diff --git a/pkg/test/image-utils/images.go b/pkg/test/image-utils/images.go index da0386eb..998ba88b 100644 --- a/pkg/test/image-utils/images.go +++ b/pkg/test/image-utils/images.go @@ -312,7 +312,7 @@ func (ib *BaseImageBuilder) EmptyLayer() ConfigBuilder { } func (ib *BaseImageBuilder) RandomLayers(count, size int) ConfigBuilder { - for i := 0; i < count; i++ { + for range count { layer := make([]byte, size) _, err := rand.Read(layer) diff --git a/pkg/test/image-utils/utils.go b/pkg/test/image-utils/utils.go index a5348b72..c96314ec 100644 --- a/pkg/test/image-utils/utils.go +++ b/pkg/test/image-utils/utils.go @@ -143,13 +143,14 @@ func GetDefaultVulnConfig() ispec.Image { } } +// RandomString generates a random string. // Adapted from https://gist.github.com/dopey/c69559607800d2f2f90b1b1ed4e550fb func RandomString(n int) string { const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-" ret := make([]byte, n) - for count := 0; count < n; count++ { + for count := range n { num, err := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))) if err != nil { panic(err) diff --git a/pkg/test/inject/dev.go b/pkg/test/inject/dev.go index f47880a7..79bbd154 100644 --- a/pkg/test/inject/dev.go +++ b/pkg/test/inject/dev.go @@ -1,5 +1,4 @@ //go:build dev -// +build dev // This file should be linked only in **development** mode. @@ -37,7 +36,7 @@ func Error(err error) error { return nil } -// Used to inject error status codes for coverage purposes. +// ErrStatusCode is used to inject error status codes for coverage purposes. // -1 will be returned in case of successful failure injection. func ErrStatusCode(status int) int { if !injectedFailure() { diff --git a/pkg/test/inject/inject_test.go b/pkg/test/inject/inject_test.go index 68f1d416..0a4faffa 100644 --- a/pkg/test/inject/inject_test.go +++ b/pkg/test/inject/inject_test.go @@ -1,5 +1,4 @@ //go:build dev -// +build dev // This file should be linked only in **development** mode. diff --git a/pkg/test/inject/prod.go b/pkg/test/inject/prod.go index 3e01b91e..1ec424d5 100644 --- a/pkg/test/inject/prod.go +++ b/pkg/test/inject/prod.go @@ -1,5 +1,4 @@ //go:build !dev -// +build !dev package inject diff --git a/pkg/test/mocks/storage_driver_mock.go b/pkg/test/mocks/storage_driver_mock.go index 3e53b353..36344220 100644 --- a/pkg/test/mocks/storage_driver_mock.go +++ b/pkg/test/mocks/storage_driver_mock.go @@ -100,7 +100,7 @@ func (s *StorageDriverMock) Delete(ctx context.Context, path string) error { return nil } -func (s *StorageDriverMock) URLFor(ctx context.Context, path string, options map[string]interface{}) (string, error) { +func (s *StorageDriverMock) URLFor(ctx context.Context, path string, options map[string]any) (string, error) { return "", nil } diff --git a/pkg/test/mocks/sync_remote_mock.go b/pkg/test/mocks/sync_remote_mock.go index db3c1421..8346c6c9 100644 --- a/pkg/test/mocks/sync_remote_mock.go +++ b/pkg/test/mocks/sync_remote_mock.go @@ -18,6 +18,7 @@ type SyncRemoteMock struct { } // Methods required by sync Remote interface. + func (remote SyncRemoteMock) GetHostName() string { if remote.GetHostNameFn != nil { return remote.GetHostNameFn() @@ -77,6 +78,7 @@ type SyncDestinationMock struct { } // Methods required by sync Destination interface. + func (dest SyncDestinationMock) GetImageReference(repo string, tag string) (ref.Ref, error) { if dest.GetImageReferenceFn != nil { return dest.GetImageReferenceFn(repo, tag) diff --git a/pkg/test/oci-utils/oci_layout.go b/pkg/test/oci-utils/oci_layout.go index f2f2b922..191e4020 100644 --- a/pkg/test/oci-utils/oci_layout.go +++ b/pkg/test/oci-utils/oci_layout.go @@ -1,5 +1,4 @@ //go:build sync && scrub && metrics && search -// +build sync,scrub,metrics,search package ociutils @@ -41,7 +40,7 @@ type OciUtils interface { //nolint: interfacebloat *ispec.Manifest, *ispec.Image, error) } -// OciLayoutInfo ... +// BaseOciLayoutUtils provides OCI layout utilities. type BaseOciLayoutUtils struct { Log log.Logger StoreController stypes.StoreController @@ -74,7 +73,7 @@ func (olu BaseOciLayoutUtils) GetImageManifest(repo string, reference string) (i return manifest, digest, nil } -// Provide a list of repositories from all the available image stores. +// GetRepositories provides a list of repositories from all the available image stores. func (olu BaseOciLayoutUtils) GetRepositories() ([]string, error) { defaultStore := olu.StoreController.GetDefaultImageStore() substores := olu.StoreController.GetImageSubStores() @@ -96,7 +95,7 @@ func (olu BaseOciLayoutUtils) GetRepositories() ([]string, error) { return repoList, nil } -// Below method will return image path including root dir, root dir is determined by splitting. +// GetImageManifests returns image path including root dir, root dir is determined by splitting. func (olu BaseOciLayoutUtils) GetImageManifests(repo string) ([]ispec.Descriptor, error) { var lockLatency time.Time @@ -287,9 +286,9 @@ func (olu BaseOciLayoutUtils) checkCosignSignature(name string, digest godigest. return true } -// checks if manifest is signed or not -// checks for notary or cosign signature -// if cosign signature found it does not looks for notary signature. +// CheckManifestSignature checks if manifest is signed or not. +// It checks for notary or cosign signature. +// If cosign signature found it does not look for notary signature. func (olu BaseOciLayoutUtils) CheckManifestSignature(name string, digest godigest.Digest) bool { if !olu.checkCosignSignature(name, digest) { return olu.checkNotarySignature(name, digest) @@ -556,7 +555,6 @@ func (olu BaseOciLayoutUtils) GetExpandedRepoInfo(repoName string) (common.RepoI repoVendors := make([]string, 0, len(repoVendorsSet)) for vendor := range repoVendorsSet { - vendor := vendor repoVendors = append(repoVendors, vendor) } diff --git a/pkg/test/oci-utils/oci_layout_test.go b/pkg/test/oci-utils/oci_layout_test.go index 3fe7317f..d8b986a7 100644 --- a/pkg/test/oci-utils/oci_layout_test.go +++ b/pkg/test/oci-utils/oci_layout_test.go @@ -1,5 +1,4 @@ //go:build sync && scrub && metrics && search -// +build sync,scrub,metrics,search package ociutils_test diff --git a/pkg/test/oci-utils/repo.go b/pkg/test/oci-utils/repo.go index 327b5d4d..6e842b85 100644 --- a/pkg/test/oci-utils/repo.go +++ b/pkg/test/oci-utils/repo.go @@ -3,6 +3,7 @@ package ociutils import ( "context" "fmt" + "maps" zerr "zotregistry.dev/zot/v2/errors" mTypes "zotregistry.dev/zot/v2/pkg/meta/types" @@ -12,12 +13,14 @@ import ( type RepoImage struct { imageUtil.Image + Reference string Statistics mTypes.DescriptorStatistics } type RepoMultiArchImage struct { imageUtil.MultiarchImage + ImageStatistics map[mTypes.ImageDigest]mTypes.DescriptorStatistics Reference string } @@ -83,14 +86,10 @@ func InitializeTestMetaDB(ctx context.Context, metaDB mTypes.MetaDB, repos ...Re repoMeta.IsBookmarked = repo.IsBookmarked // updateStatistics - for key, value := range statistics { - repoMeta.Statistics[key] = value - } + maps.Copy(repoMeta.Statistics, statistics) // update signatures? - for key, value := range repo.Signatures { - repoMeta.Signatures[key] = value - } + maps.Copy(repoMeta.Signatures, repo.Signatures) err = metaDB.SetRepoMeta(repo.Name, repoMeta) if err != nil { diff --git a/pkg/test/signature/notation_test.go b/pkg/test/signature/notation_test.go index e2012f1a..b8df0bc3 100644 --- a/pkg/test/signature/notation_test.go +++ b/pkg/test/signature/notation_test.go @@ -1,5 +1,4 @@ //go:build sync && scrub && metrics && search -// +build sync,scrub,metrics,search package signature_test diff --git a/tools.go b/tools.go index 4f04ccd8..932931d3 100644 --- a/tools.go +++ b/tools.go @@ -1,5 +1,4 @@ //go:build tools -// +build tools package tools