chore: update golangci-lint and fix all issues (#3575)

* chore: Update golangci-lint

Signed-off-by: Lars Francke <git@lars-francke.de>

* chore: fix all golangci-lint issues

- Remove deprecated `// +build` tags
- Fix godoclint, modernize, wsl_v5, govet, lll, gci, noctx issues
- Update linter configuration
- Modernize code to use Go 1.22+ features (for range N, slices.Contains, etc.)
- Update make check lint the privileged tests

Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>

---------

Signed-off-by: Lars Francke <git@lars-francke.de>
Signed-off-by: Andrei Aaron <andreifdaaron@gmail.com>
Co-authored-by: Lars Francke <git@lars-francke.de>
This commit is contained in:
Andrei Aaron
2025-11-22 23:36:48 +02:00
committed by GitHub
parent 566286ae42
commit da426850e7
242 changed files with 811 additions and 1010 deletions
+2 -2
View File
@@ -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
+16 -3
View File
@@ -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:
+13 -8
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+32 -18
View File
@@ -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)
}
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package main
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package main_test
-1
View File
@@ -1,5 +1,4 @@
//go:build !metrics
// +build !metrics
package main
+2 -1
View File
@@ -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...)
}
+2 -1
View File
@@ -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
}
+17 -19
View File
@@ -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
+3 -2
View File
@@ -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 {
+9 -11
View File
@@ -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
-1
View File
@@ -1,5 +1,4 @@
//go:build needprivileges
// +build needprivileges
package config_test
+3 -3
View File
@@ -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",
},
},
+10 -10
View File
@@ -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
+10 -10
View File
@@ -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{},
+9 -7
View File
@@ -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"
)
+5 -5
View File
@@ -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
+2 -2
View File
@@ -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()
+43 -43
View File
@@ -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
+3 -2
View File
@@ -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
+3 -3
View File
@@ -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
}
+15 -11
View File
@@ -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)
-2
View File
@@ -1,5 +1,3 @@
// Package ldap provides a simple ldap client to authenticate,
// retrieve basic information and groups for a user.
package api
import (
+4 -4
View File
@@ -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
-1
View File
@@ -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
+6 -4
View File
@@ -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),
+2 -3
View File
@@ -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"},
}
-1
View File
@@ -1,5 +1,4 @@
//go:build !windows
// +build !windows
package api
-1
View File
@@ -1,5 +1,4 @@
//go:build windows
// +build windows
package api
+1
View File
@@ -16,6 +16,7 @@ import (
type statusWriter struct {
http.ResponseWriter
status int
length int
}
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
+4 -6
View File
@@ -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
}
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client_test
+20 -23
View File
@@ -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 (
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client_test
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-3
View File
@@ -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
}
}
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
+5 -1
View File
@@ -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()
+5 -6
View File
@@ -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())
}
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client_test
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client_test
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client_test
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client_test
+1 -2
View File
@@ -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
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client_test
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client_test
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
@@ -1,5 +1,4 @@
//go:build search
// +build search
//
//nolint:dupl
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client //nolint:testpackage
+1 -2
View File
@@ -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 {
+4 -5
View File
@@ -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
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package client
-1
View File
@@ -1,5 +1,4 @@
//go:build search
// +build search
package server_test
-1
View File
@@ -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
+3 -3
View File
@@ -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 = ""
}
+29 -28
View File
@@ -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()
}()
+3 -1
View File
@@ -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
-1
View File
@@ -1,5 +1,4 @@
//go:build !sync
// +build !sync
package server
-1
View File
@@ -1,5 +1,4 @@
//go:build sync
// +build sync
package server
+5 -2
View File
@@ -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...")
+24 -24
View File
@@ -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"`
}
+2 -2
View File
@@ -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
+15 -38
View File
@@ -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 {
+4 -8
View File
@@ -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)
})
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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)
+26 -13
View File
@@ -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 {
+5 -21
View File
@@ -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) {
+1 -1
View File
@@ -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 {
-1
View File
@@ -1,5 +1,4 @@
//go:build debug
// +build debug
package debug
@@ -1,5 +1,4 @@
//go:build !debug
// +build !debug
package debug
-1
View File
@@ -1,5 +1,4 @@
//go:build profile
// +build profile
package pprof
-1
View File
@@ -1,5 +1,4 @@
//go:build !profile
// +build !profile
package pprof
-1
View File
@@ -1,5 +1,4 @@
//go:build profile
// +build profile
package pprof_test
+2 -1
View File
@@ -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"
)
-1
View File
@@ -1,5 +1,4 @@
//go:build !debug
// +build !debug
// @contact.name API Support
// @contact.url http://www.swagger.io/support
+1 -2
View File
@@ -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
-1
View File
@@ -1,5 +1,4 @@
//go:build !metrics
// +build !metrics
package api
+4 -4
View File
@@ -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() {
+2 -3
View File
@@ -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 {
-1
View File
@@ -1,5 +1,4 @@
//go:build !metrics
// +build !metrics
package cli
-1
View File
@@ -1,5 +1,4 @@
//go:build !metrics
// +build !metrics
package cli_test
+10 -5
View File
@@ -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 {
+10 -10
View File
@@ -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
}

Some files were not shown because too many files have changed in this diff Show More