mirror of
https://github.com/project-zot/zot.git
synced 2026-06-15 11:37:56 +08:00
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:
@@ -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
|
||||
|
||||
@@ -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:
|
||||
@@ -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
@@ -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
@@ -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
@@ -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,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package main
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package main_test
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build !metrics
|
||||
// +build !metrics
|
||||
|
||||
package main
|
||||
|
||||
|
||||
+2
-1
@@ -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...)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build needprivileges
|
||||
// +build needprivileges
|
||||
|
||||
package config_test
|
||||
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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{},
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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,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
@@ -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),
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package api
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build windows
|
||||
// +build windows
|
||||
|
||||
package api
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
|
||||
type statusWriter struct {
|
||||
http.ResponseWriter
|
||||
|
||||
status int
|
||||
length int
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client_test
|
||||
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client_test
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client_test
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client_test
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client_test
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client_test
|
||||
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client_test
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client_test
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
//
|
||||
//nolint:dupl
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client //nolint:testpackage
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package client
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build search
|
||||
// +build search
|
||||
|
||||
package server_test
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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()
|
||||
}()
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build !sync
|
||||
// +build !sync
|
||||
|
||||
package server
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build sync
|
||||
// +build sync
|
||||
|
||||
package server
|
||||
|
||||
|
||||
@@ -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...")
|
||||
|
||||
@@ -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,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
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build debug
|
||||
// +build debug
|
||||
|
||||
package debug
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build !debug
|
||||
// +build !debug
|
||||
|
||||
package debug
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build profile
|
||||
// +build profile
|
||||
|
||||
package pprof
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build !profile
|
||||
// +build !profile
|
||||
|
||||
package pprof
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build profile
|
||||
// +build profile
|
||||
|
||||
package pprof_test
|
||||
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build !debug
|
||||
// +build !debug
|
||||
|
||||
// @contact.name API Support
|
||||
// @contact.url http://www.swagger.io/support
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build !metrics
|
||||
// +build !metrics
|
||||
|
||||
package api
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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,5 +1,4 @@
|
||||
//go:build !metrics
|
||||
// +build !metrics
|
||||
|
||||
package cli
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
//go:build !metrics
|
||||
// +build !metrics
|
||||
|
||||
package cli_test
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user