From f618b1d4effec4c52381bff701a3bc62274666ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Otto=20Kr=C3=B6pke?= Date: Mon, 29 Jul 2024 19:32:51 +0200 Subject: [PATCH] ci(deps): upgrade golangci-lint (#2556) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci(deps): upgrade golangci-lint Signed-off-by: Jan-Otto Kröpke * build(deps): removed disabled linters Signed-off-by: Jan-Otto Kröpke * build(deps): go run github.com/daixiang0/gci@latest write . Signed-off-by: Jan-Otto Kröpke * build(deps): go run golang.org/x/tools/cmd/goimports@latest -l -w . Signed-off-by: Jan-Otto Kröpke * build(deps): go run github.com/bombsimon/wsl/v4/cmd...@latest -strict-append -test=true -fix ./... Signed-off-by: Jan-Otto Kröpke * build(deps): go run github.com/catenacyber/perfsprint@latest -fix ./... Signed-off-by: Jan-Otto Kröpke * build(deps): replace gomnd by mnd Signed-off-by: Jan-Otto Kröpke * build(deps): make gqlgen Signed-off-by: Jan-Otto Kröpke * build: Revert "build(deps): go run github.com/daixiang0/gci@latest write ." This reverts commit 5bf8c42e1f48c7daf8d1a4dbcfbb8ddef8d0bbbf. Signed-off-by: Jan-Otto Kröpke * build(deps): go run github.com/daixiang0/gci@latest write -s 'standard' -s default -s 'prefix(zotregistry.dev/zot)' . Signed-off-by: Jan-Otto Kröpke * build(deps): make gqlgen Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: wsl issues Signed-off-by: Jan-Otto Kröpke * fix: check-log issues Signed-off-by: Jan-Otto Kröpke * fix: gci issues Signed-off-by: Jan-Otto Kröpke * fix: tests Signed-off-by: Jan-Otto Kröpke --------- Signed-off-by: Jan-Otto Kröpke Signed-off-by: Jan-Otto Kröpke --- .github/workflows/golangci-lint.yaml | 2 +- Makefile | 2 +- cmd/zb/helper.go | 20 +- cmd/zb/perf.go | 7 +- errors/errors.go | 1 + golangcilint.yaml | 51 +- pkg/api/authn.go | 14 +- pkg/api/authn_test.go | 5 +- pkg/api/authz.go | 5 +- pkg/api/config/config.go | 1 + pkg/api/config/config_test.go | 3 + pkg/api/controller.go | 1 + pkg/api/controller_test.go | 579 ++++++++++++++---- pkg/api/cookiestore.go | 2 +- pkg/api/ldap.go | 4 +- pkg/api/routes.go | 32 +- pkg/api/routes_test.go | 3 + pkg/api/session.go | 18 +- pkg/cli/client/client.go | 2 +- pkg/cli/client/client_test.go | 15 + pkg/cli/client/config_cmd.go | 2 +- pkg/cli/client/config_cmd_test.go | 89 ++- pkg/cli/client/cve_cmd_internal_test.go | 64 +- pkg/cli/client/cve_cmd_test.go | 94 ++- pkg/cli/client/elevated_test.go | 10 + pkg/cli/client/image_cmd_internal_test.go | 57 +- pkg/cli/client/image_cmd_test.go | 59 +- pkg/cli/client/search_cmd_test.go | 6 + pkg/cli/client/server_info_cmd.go | 6 +- pkg/cli/client/service.go | 19 +- pkg/cli/client/utils.go | 2 +- pkg/cli/client/utils_internal_test.go | 4 +- pkg/cli/server/config_reloader_test.go | 5 + pkg/cli/server/extensions_test.go | 89 +++ pkg/cli/server/root.go | 10 +- pkg/cli/server/root_test.go | 129 +++- pkg/cli/server/stress_test.go | 8 + pkg/common/common_test.go | 7 +- pkg/common/http_client.go | 2 - pkg/compliance/v1_0_0/check.go | 16 +- pkg/debug/pprof/pprof_test.go | 4 + pkg/exporter/api/controller_test.go | 18 + pkg/exporter/api/exporter.go | 2 +- pkg/extensions/extension_image_trust.go | 2 +- pkg/extensions/extension_image_trust_test.go | 25 +- pkg/extensions/extension_scrub.go | 2 +- pkg/extensions/extension_ui_test.go | 1 + pkg/extensions/extension_userprefs_test.go | 28 +- pkg/extensions/extensions_test.go | 21 +- .../get_extensions_disabled_test.go | 2 + pkg/extensions/imagetrust/image_trust.go | 4 +- pkg/extensions/imagetrust/image_trust_test.go | 39 +- pkg/extensions/imagetrust/notation.go | 4 +- pkg/extensions/lint/lint_test.go | 28 +- pkg/extensions/monitoring/common.go | 1 + pkg/extensions/monitoring/extension.go | 2 +- pkg/extensions/monitoring/minimal.go | 2 + pkg/extensions/monitoring/monitoring_test.go | 5 +- pkg/extensions/scrub/scrub.go | 8 +- pkg/extensions/scrub/scrub_test.go | 3 +- .../search/convert/convert_internal_test.go | 1 + pkg/extensions/search/cve/cve.go | 2 + pkg/extensions/search/cve/cve_test.go | 71 ++- pkg/extensions/search/cve/pagination_test.go | 9 + pkg/extensions/search/cve/scan.go | 2 +- pkg/extensions/search/cve/scan_test.go | 2 + pkg/extensions/search/cve/trivy/scanner.go | 5 +- pkg/extensions/search/cve/update_test.go | 1 + pkg/extensions/search/digest_test.go | 1 + pkg/extensions/search/resolver.go | 2 + pkg/extensions/search/resolver_test.go | 4 + pkg/extensions/search/search_test.go | 51 +- pkg/extensions/search/userprefs_test.go | 3 + pkg/extensions/sync/content_internal_test.go | 3 + pkg/extensions/sync/destination.go | 2 +- pkg/extensions/sync/httpclient/client.go | 2 +- pkg/extensions/sync/references/cosign.go | 1 - pkg/extensions/sync/service.go | 3 +- pkg/extensions/sync/sync.go | 4 +- pkg/extensions/sync/sync_internal_test.go | 5 +- pkg/extensions/sync/sync_test.go | 363 ++++++++--- pkg/log/log.go | 1 + pkg/log/log_test.go | 24 + pkg/meta/boltdb/boltdb.go | 3 + pkg/meta/boltdb/boltdb_test.go | 4 + pkg/meta/convert/convert_proto.go | 1 + pkg/meta/dynamodb/dynamodb.go | 5 +- pkg/meta/dynamodb/dynamodb_internal_test.go | 3 +- pkg/meta/dynamodb/dynamodb_test.go | 11 + pkg/meta/dynamodb/iterator.go | 6 +- pkg/meta/hooks.go | 1 + pkg/meta/meta_test.go | 12 +- pkg/meta/parse_test.go | 3 + pkg/meta/proto/gen/config.pb.go | 5 +- pkg/meta/proto/gen/descriptor.pb.go | 5 +- pkg/meta/proto/gen/index.pb.go | 5 +- pkg/meta/proto/gen/manifest.pb.go | 5 +- pkg/meta/proto/gen/meta.pb.go | 5 +- pkg/meta/proto/gen/versioned.pb.go | 5 +- pkg/meta/version/version_test.go | 1 + pkg/retention/matcher.go | 1 + pkg/scheduler/scheduler.go | 5 +- pkg/scheduler/scheduler_test.go | 11 +- pkg/storage/cache.go | 8 +- pkg/storage/cache/boltdb.go | 2 +- pkg/storage/cache/dynamodb.go | 2 +- pkg/storage/cache/dynamodb_test.go | 2 + pkg/storage/cache_benchmark_test.go | 1 + pkg/storage/common/common.go | 8 +- pkg/storage/common/common_test.go | 2 + pkg/storage/gc/gc.go | 10 +- pkg/storage/gc/gc_internal_test.go | 3 + pkg/storage/imagestore/imagestore.go | 9 +- pkg/storage/local/driver.go | 5 +- pkg/storage/local/driver_test.go | 1 + pkg/storage/local/local_elevated_test.go | 2 + pkg/storage/local/local_test.go | 86 ++- pkg/storage/s3/s3_test.go | 69 ++- pkg/storage/scrub.go | 3 - pkg/storage/scrub_test.go | 3 + pkg/storage/storage.go | 2 +- pkg/storage/storage_controller.go | 7 +- pkg/storage/storage_test.go | 56 ++ pkg/test/auth/bearer.go | 3 + pkg/test/auth/oidc.go | 5 +- pkg/test/common/fs.go | 3 +- pkg/test/common/fs_test.go | 7 + pkg/test/common/utils.go | 3 +- pkg/test/image-utils/upload.go | 11 +- pkg/test/image-utils/upload_test.go | 5 + pkg/test/image-utils/utils.go | 12 +- pkg/test/mocks/repo_db_mock.go | 2 +- pkg/test/mocks/sync_remote_mock.go | 2 +- pkg/test/oci-utils/oci_layout.go | 2 +- pkg/test/oci-utils/oci_layout_test.go | 5 +- pkg/test/oci-utils/repo_test.go | 4 +- pkg/test/signature/notation.go | 8 +- pkg/test/signature/notation_test.go | 18 +- pkg/test/skip/skip_test.go | 6 +- 139 files changed, 2188 insertions(+), 494 deletions(-) diff --git a/.github/workflows/golangci-lint.yaml b/.github/workflows/golangci-lint.yaml index 344cf1e2..26b9d0e5 100644 --- a/.github/workflows/golangci-lint.yaml +++ b/.github/workflows/golangci-lint.yaml @@ -24,7 +24,7 @@ jobs: uses: golangci/golangci-lint-action@v6 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: v1.54.2 + version: v1.59.1 # Optional: working directory, useful for monorepos # working-directory: somedir diff --git a/Makefile b/Makefile index 2afab068..3a6b63fe 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ TOOLSDIR := $(shell pwd)/hack/tools PATH := bin:$(TOOLSDIR)/bin:$(PATH) STACKER := $(shell which stacker) GOLINTER := $(TOOLSDIR)/bin/golangci-lint -GOLINTER_VERSION := v1.54.2 +GOLINTER_VERSION := v1.59.1 NOTATION := $(TOOLSDIR)/bin/notation NOTATION_VERSION := 1.0.0 COSIGN := $(TOOLSDIR)/bin/cosign diff --git a/cmd/zb/helper.go b/cmd/zb/helper.go index 6cfda833..5a5d93ff 100644 --- a/cmd/zb/helper.go +++ b/cmd/zb/helper.go @@ -11,6 +11,7 @@ import ( "net/url" "os" "path" + "strconv" "sync" "time" @@ -368,9 +369,8 @@ func pushMonolithImage(workdir, url, trepo string, repos []string, config testCo resp, err = client.R(). SetContentLength(true). SetQueryParam("digest", digest.String()). - SetHeader("Content-Length", fmt.Sprintf("%d", size)). + SetHeader("Content-Length", strconv.Itoa(size)). SetHeader("Content-Type", "application/octet-stream").SetBody(fhandle).Put(loc) - if err != nil { return nil, repos, err } @@ -385,7 +385,6 @@ func pushMonolithImage(workdir, url, trepo string, repos []string, config testCo // upload image config blob resp, err = client.R(). Post(fmt.Sprintf("%s/v2/%s/blobs/uploads/", url, repo)) - if err != nil { return nil, repos, err } @@ -399,14 +398,14 @@ func pushMonolithImage(workdir, url, trepo string, repos []string, config testCo loc = getLocation(url, resp) cblob, cdigest := getImageConfig() + resp, err = client.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). Put(loc) - if err != nil { return nil, repos, err } @@ -450,7 +449,6 @@ func pushMonolithImage(workdir, url, trepo string, repos []string, config testCo SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). SetBody(content). Put(fmt.Sprintf("%s/v2/%s/manifests/%s", url, repo, manifestTag)) - if err != nil { return nil, repos, err } @@ -551,7 +549,7 @@ func pushMonolithAndCollect(workdir, url, trepo string, count int, resp, err = client.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", size)). + SetHeader("Content-Length", strconv.Itoa(size)). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest.String()). SetBody(fhandle). @@ -597,7 +595,7 @@ func pushMonolithAndCollect(workdir, url, trepo string, count int, cblob, cdigest := getImageConfig() resp, err = client.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -780,7 +778,7 @@ func pushChunkAndCollect(workdir, url, trepo string, count int, // finish upload resp, err = client.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", size)). + SetHeader("Content-Length", strconv.Itoa(size)). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest.String()). Put(loc) @@ -823,12 +821,12 @@ func pushChunkAndCollect(workdir, url, trepo string, count int, loc = getLocation(url, resp) cblob, cdigest := getImageConfig() + resp, err = client.R(). SetContentLength(true). SetHeader("Content-Type", "application/octet-stream"). SetBody(fhandle). Patch(loc) - if err != nil { isConnFail = true @@ -871,7 +869,7 @@ func pushChunkAndCollect(workdir, url, trepo string, count int, // finish upload resp, err = client.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). Put(loc) diff --git a/cmd/zb/perf.go b/cmd/zb/perf.go index 2cc61fce..206f875a 100644 --- a/cmd/zb/perf.go +++ b/cmd/zb/perf.go @@ -466,6 +466,7 @@ func Pull( } else { // Push blob given size var err error + manifestHash, repos, err = pushMonolithImage(workdir, url, trepo, repos, config, client) if err != nil { return err @@ -684,6 +685,7 @@ func Perf( log.Printf("Starting tests ...\n") var err error + zbError := false // get host ips from command line to make requests from @@ -724,6 +726,7 @@ func Perf( } }() } + wg.Wait() summary.total = time.Since(start) @@ -757,7 +760,7 @@ func Perf( log.Fatal(err) // file closed on exit } - if err := os.WriteFile(fmt.Sprintf("%s.json", outFmt), jsonOut, defaultFilePerms); err != nil { + if err := os.WriteFile(outFmt+".json", jsonOut, defaultFilePerms); err != nil { log.Fatal(err) } } @@ -788,7 +791,7 @@ func getRandomClientIPs(auth string, url string, ips []string) (*resty.Client, e ip := ips[nBig.Int64()] // set ip in transport - localAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:0", ip)) + localAddr, err := net.ResolveTCPAddr("tcp", ip+":0") if err != nil { return nil, err } diff --git a/errors/errors.go b/errors/errors.go index 84bf769c..f46569ea 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -36,6 +36,7 @@ func NewError(err error) *Error { func GetDetails(err error) map[string]string { var internalErr *Error + details := make(map[string]string) if errors.As(err, &internalErr) { diff --git a/golangcilint.yaml b/golangcilint.yaml index 7a866bda..376d59e7 100644 --- a/golangcilint.yaml +++ b/golangcilint.yaml @@ -1,11 +1,31 @@ run: - deadline: 60m - skip-dirs: - - "internal" + timeout: 60m linters: enable-all: true - disable: funlen,gocognit,exhaustivestruct,paralleltest,forbidigo,ireturn,wrapcheck,exhaustive,maintidx,exhaustruct,nosnakecase,interfacer,structcheck,varcheck,deadcode,ifshort,golint,scopelint,maligned,rowserrcheck,sqlclosecheck,revive,musttag,depguard + disable: + - gomnd + - funlen + - gocognit + - paralleltest + - forbidigo + - ireturn + - wrapcheck + - exhaustive + - maintidx + - exhaustruct + - rowserrcheck + - sqlclosecheck + - revive + - musttag + - depguard + - execinquery + - inamedparam + - intrange + - promlinter + - protogetter + - contextcheck # needs to revisit: https://github.com/project-zot/zot/pull/2556 + - copyloopvar # needs to revisit: https://github.com/project-zot/zot/pull/2556 linters-settings: dupl: @@ -41,22 +61,33 @@ linters-settings: - prefix(zotregistry.dev/zot) wsl: allow-assign-and-anything: true - enforce-err-cuddling: true + force-err-cuddling: true nolintlint: allow-unused: true - gomnd: - settings: - mnd: - checks: argument,case,condition,operation,return,assign - ignored-numbers: 10,64 + mnd: + checks: + - argument + - case + - condition + - operation + - return + - assign + ignored-numbers: + - "10" + - "64" gomoddirectives: replace-allow-list: - github.com/gorilla/mux - github.com/testcontainers/testcontainers-go issues: + exclude-dirs: + - "internal" exclude-rules: - path: pkg/extensions/search/schema.resolvers.go linters: - lll - varnamelen - gci + - path: _test\.go + linters: + - dupl diff --git a/pkg/api/authn.go b/pkg/api/authn.go index 47724198..0813273e 100644 --- a/pkg/api/authn.go +++ b/pkg/api/authn.go @@ -6,6 +6,7 @@ import ( "crypto/sha256" "crypto/x509" "encoding/base64" + "encoding/hex" "errors" "fmt" "net" @@ -434,6 +435,7 @@ func bearerAuthHandler(ctlr *Controller) mux.MiddlewareFunc { return } + acCtrlr := NewAccessController(ctlr.Config) vars := mux.Vars(request) name := vars["name"] @@ -661,7 +663,7 @@ func getRelyingPartyArgs(cfg *config.Config, provider string, log log.Logger) ( keyPath := cfg.HTTP.Auth.OpenID.Providers[provider].KeyPath baseURL := net.JoinHostPort(cfg.HTTP.Address, port) - callback := constants.CallbackBasePath + fmt.Sprintf("/%s", provider) + callback := constants.CallbackBasePath + "/" + provider var redirectURI string @@ -681,7 +683,7 @@ func getRelyingPartyArgs(cfg *config.Config, provider string, log log.Logger) ( rp.WithVerifierOpts(rp.WithIssuedAtOffset(issuedAtOffset)), } - key := securecookie.GenerateRandomKey(32) //nolint: gomnd + key := securecookie.GenerateRandomKey(32) //nolint:mnd cookieHandler := httphelper.NewCookieHandler(key, key, httphelper.WithMaxAge(relyingPartyCookieMaxAge)) options = append(options, rp.WithCookieHandler(cookieHandler)) @@ -740,7 +742,7 @@ func getUsernamePasswordBasicAuth(request *http.Request) (string, string, error) return "", "", zerr.ErrParsingAuthHeader } - splitStr := strings.SplitN(basicAuth, " ", 2) //nolint: gomnd + splitStr := strings.SplitN(basicAuth, " ", 2) //nolint:mnd if len(splitStr) != 2 || strings.ToLower(splitStr[0]) != "basic" { return "", "", zerr.ErrParsingAuthHeader } @@ -750,8 +752,8 @@ func getUsernamePasswordBasicAuth(request *http.Request) (string, string, error) return "", "", err } - pair := strings.SplitN(string(decodedStr), ":", 2) //nolint: gomnd - if len(pair) != 2 { //nolint: gomnd + pair := strings.SplitN(string(decodedStr), ":", 2) //nolint:mnd + if len(pair) != 2 { //nolint:mnd return "", "", zerr.ErrParsingAuthHeader } @@ -878,7 +880,7 @@ func hashUUID(uuid string) string { digester := sha256.New() digester.Write([]byte(uuid)) - return godigest.NewDigestFromEncoded(godigest.SHA256, fmt.Sprintf("%x", digester.Sum(nil))).Encoded() + return godigest.NewDigestFromEncoded(godigest.SHA256, hex.EncodeToString(digester.Sum(nil))).Encoded() } /* diff --git a/pkg/api/authn_test.go b/pkg/api/authn_test.go index 2900e2f0..cd33940e 100644 --- a/pkg/api/authn_test.go +++ b/pkg/api/authn_test.go @@ -7,7 +7,6 @@ import ( "context" "encoding/json" "errors" - "fmt" "io/fs" "net/http" "net/http/httptest" @@ -91,6 +90,7 @@ func TestAPIKeys(t *testing.T) { username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) mockOIDCServer, err := authutils.MockOIDCRun() @@ -847,6 +847,7 @@ func TestAPIKeysOpenDBError(t *testing.T) { username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) mockOIDCServer, err := authutils.MockOIDCRun() @@ -1107,7 +1108,7 @@ func (gen *mockUUIDGenerator) NewV4() ( type errReader int func (errReader) Read(p []byte) (int, error) { - return 0, fmt.Errorf("test error") //nolint:goerr113 + return 0, errors.New("test error") //nolint:goerr113 } type badDirInfo struct { diff --git a/pkg/api/authz.go b/pkg/api/authz.go index 5d32533e..efb91c63 100644 --- a/pkg/api/authz.go +++ b/pkg/api/authz.go @@ -230,7 +230,6 @@ func BaseAuthzHandler(ctlr *Controller) mux.MiddlewareFunc { since we only do READ actions in extensions, this middleware is enough for them because it populates the context with user relevant data to be processed by each individual extension */ - if request.Method == http.MethodOptions { next.ServeHTTP(response, request) @@ -312,9 +311,10 @@ func DistSpecAuthzHandler(ctlr *Controller) mux.MiddlewareFunc { // if we get a reference (tag) if ok { is := ctlr.StoreController.GetImageStore(resource) + tags, err := is.GetImageTags(resource) - // if repo exists and request's tag exists then action is UPDATE if err == nil && common.Contains(tags, reference) && reference != "latest" { + // if repo exists and request's tag exists then action is UPDATE action = constants.UpdatePermission } } @@ -343,6 +343,7 @@ func MetricsAuthzHandler(ctlr *Controller) mux.MiddlewareFunc { return } + if len(ctlr.Config.HTTP.AccessControl.Metrics.Users) == 0 { log := ctlr.Log log.Warn().Msg("auth is enabled but no metrics users in accessControl: /metrics is unaccesible") diff --git a/pkg/api/config/config.go b/pkg/api/config/config.go index 18899e1a..062787af 100644 --- a/pkg/api/config/config.go +++ b/pkg/api/config/config.go @@ -306,6 +306,7 @@ func DeepCopy(src, dst interface{}) error { if err != nil { return err } + err = json.Unmarshal(bytes, dst) return err diff --git a/pkg/api/config/config_test.go b/pkg/api/config/config_test.go index 34962638..61e4d629 100644 --- a/pkg/api/config/config_test.go +++ b/pkg/api/config/config_test.go @@ -69,9 +69,12 @@ func TestConfig(t *testing.T) { Convey("Test DeepCopy() & Sanitize()", t, func() { conf := config.New() So(conf, ShouldNotBeNil) + authConfig := &config.AuthConfig{LDAP: (&config.LDAPConfig{}).SetBindPassword("oina")} conf.HTTP.Auth = authConfig + So(func() { conf.Sanitize() }, ShouldNotPanic) + conf = conf.Sanitize() So(conf.HTTP.Auth.LDAP.BindPassword(), ShouldEqual, "******") diff --git a/pkg/api/controller.go b/pkg/api/controller.go index d86d697a..8408f4c9 100644 --- a/pkg/api/controller.go +++ b/pkg/api/controller.go @@ -96,6 +96,7 @@ func NewController(appConfig *config.Config) *Controller { Str("clusterMember", memberSocket). Str("clusterMemberIndex", strconv.Itoa(memberSocketIdx)).Logger() } + controller.Config = appConfig controller.Log = logger diff --git a/pkg/api/controller_test.go b/pkg/api/controller_test.go index c8d84710..cd67fb5f 100644 --- a/pkg/api/controller_test.go +++ b/pkg/api/controller_test.go @@ -44,6 +44,7 @@ import ( "github.com/sigstore/cosign/v2/pkg/oci/remote" . "github.com/smartystreets/goconvey/convey" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "go.etcd.io/bbolt" "gopkg.in/resty.v1" @@ -106,6 +107,7 @@ func TestNew(t *testing.T) { conf.Cluster = &config.ClusterConfig{ Members: []string{}, } + So(func() { api.NewController(conf) }, ShouldPanicWith, "failed to determine the local cluster socket") }) @@ -119,6 +121,7 @@ func TestNew(t *testing.T) { conf.Cluster = &config.ClusterConfig{ Members: []string{"127.0.0.1"}, } + So(func() { api.NewController(conf) }, ShouldPanicWith, "failed to get member socket") }) } @@ -323,6 +326,7 @@ func TestRunAlreadyRunningServer(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() err := ctlr.Init() @@ -340,7 +344,9 @@ func TestAutoPortSelection(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // clean up ctlr := makeController(conf, t.TempDir()) @@ -348,28 +354,35 @@ func TestAutoPortSelection(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartServer() time.Sleep(1000 * time.Millisecond) + defer cm.StopServer() file, err := os.Open(logFile.Name()) So(err, ShouldBeNil) + defer file.Close() scanner := bufio.NewScanner(file) var contents bytes.Buffer + start := time.Now() for scanner.Scan() { if time.Since(start) < time.Second*30 { t.Logf("Exhausted: Controller did not print the expected log within 30 seconds") } + text := scanner.Text() contents.WriteString(text) + if strings.Contains(text, "Port unspecified") { break } + t.Logf(scanner.Text()) } + So(scanner.Err(), ShouldBeNil) So(contents.String(), ShouldContainSubstring, "port is unspecified, listening on kernel chosen port", @@ -430,6 +443,7 @@ func TestObjectStorageController(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() }) @@ -504,6 +518,7 @@ func TestObjectStorageController(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() }) } @@ -543,6 +558,7 @@ func TestObjectStorageControllerSubPaths(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() }) } @@ -577,6 +593,7 @@ func TestHtpasswdSingleCred(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // with creds, should get expected status code @@ -615,6 +632,7 @@ func TestAllowMethodsHeader(t *testing.T) { simpleUser := "simpleUser" simpleUserPassword := "simpleUserPass" htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(simpleUser, simpleUserPassword)) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -705,8 +723,10 @@ func TestHtpasswdTwoCreds(t *testing.T) { baseURL := test.GetBaseURL(port) conf := config.New() conf.HTTP.Port = port + htpasswdPath := test.MakeHtpasswdFileFromString(testString) defer os.Remove(htpasswdPath) + conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ Path: htpasswdPath, @@ -715,6 +735,7 @@ func TestHtpasswdTwoCreds(t *testing.T) { ctlr := makeController(conf, t.TempDir()) cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // with creds, should get expected status code @@ -745,6 +766,7 @@ func TestHtpasswdFiveCreds(t *testing.T) { "creed": "bratton", } credString := strings.Builder{} + for key, val := range tests { credString.WriteString(test.GetCredString(key, val) + "\n") } @@ -755,6 +777,7 @@ func TestHtpasswdFiveCreds(t *testing.T) { conf := config.New() conf.HTTP.Port = port htpasswdPath := test.MakeHtpasswdFileFromString(credString.String()) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ @@ -765,6 +788,7 @@ func TestHtpasswdFiveCreds(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // with creds, should get expected status code @@ -797,6 +821,7 @@ func TestRatelimit(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() Convey("Ratelimit", func() { @@ -832,7 +857,9 @@ func TestRatelimit(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() + Convey("Method Ratelimit", func() { client := resty.New() // first request should succeed @@ -868,6 +895,7 @@ func TestRatelimit(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() Convey("Global and Method Ratelimit", func() { client := resty.New() @@ -893,7 +921,9 @@ func TestBasicAuth(t *testing.T) { conf.HTTP.Port = port username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -906,6 +936,7 @@ func TestBasicAuth(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // without creds, should get access error @@ -913,7 +944,9 @@ func TestBasicAuth(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + var e apiErr.Error + err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) @@ -939,6 +972,7 @@ func TestBlobReferenced(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // without creds, should get access error @@ -990,7 +1024,7 @@ func TestScaleOutRequestProxy(t *testing.T) { Convey("Given a zot scale out cluster in http mode with only 1 member", t, func() { port := test.GetFreePort() clusterMembers := make([]string, 1) - clusterMembers[0] = fmt.Sprintf("127.0.0.1:%s", port) + clusterMembers[0] = "127.0.0.1:" + port conf := config.New() conf.HTTP.Port = port @@ -1002,6 +1036,7 @@ func TestScaleOutRequestProxy(t *testing.T) { ctrlr := makeController(conf, t.TempDir()) cm := test.NewControllerManager(ctrlr) cm.StartAndWait(port) + defer cm.StopServer() Convey("Controller should start up and respond without error", func() { @@ -1025,10 +1060,12 @@ func TestScaleOutRequestProxy(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) result := common.ImageTags{} + err = json.Unmarshal(resp.Body(), &result) if err != nil { t.Fatalf("Failed to unmarshal") } + So(result.Name, ShouldEqual, repoName) So(len(result.Tags), ShouldEqual, 1) So(result.Tags[0], ShouldEqual, "1.0") @@ -1041,7 +1078,7 @@ func TestScaleOutRequestProxy(t *testing.T) { Convey("Given a scale out http cluster with only 1 online member", t, func() { port := test.GetFreePort() clusterMembers := make([]string, 3) - clusterMembers[0] = fmt.Sprintf("127.0.0.1:%s", port) + clusterMembers[0] = "127.0.0.1:" + port clusterMembers[1] = "127.0.0.1:1" clusterMembers[2] = "127.0.0.1:2" @@ -1053,8 +1090,10 @@ func TestScaleOutRequestProxy(t *testing.T) { } ctrlr := makeController(conf, t.TempDir()) + cm := test.NewControllerManager(ctrlr) cm.StartAndWait(port) + defer cm.StopServer() Convey("Controller should start up and respond without error", func() { @@ -1086,10 +1125,11 @@ func TestScaleOutRequestProxy(t *testing.T) { ports := make([]string, numMembers) clusterMembers := make([]string, numMembers) + for idx := 0; idx < numMembers; idx++ { port := test.GetFreePort() ports[idx] = port - clusterMembers[idx] = fmt.Sprintf("127.0.0.1:%s", port) + clusterMembers[idx] = "127.0.0.1:" + port } for _, port := range ports { @@ -1103,6 +1143,7 @@ func TestScaleOutRequestProxy(t *testing.T) { ctrlr := makeController(conf, t.TempDir()) cm := test.NewControllerManager(ctrlr) cm.StartAndWait(port) + defer cm.StopServer() } @@ -1132,10 +1173,12 @@ func TestScaleOutRequestProxy(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) result := common.ImageTags{} + err = json.Unmarshal(resp.Body(), &result) if err != nil { t.Fatalf("Failed to unmarshal") } + So(result.Name, ShouldEqual, repoName) So(len(result.Tags), ShouldEqual, 1) So(result.Tags[0], ShouldEqual, "1.0") @@ -1151,21 +1194,27 @@ func TestScaleOutRequestProxy(t *testing.T) { ports := make([]string, numMembers) clusterMembers := make([]string, numMembers) + for idx := 0; idx < numMembers; idx++ { port := test.GetFreePort() ports[idx] = port - clusterMembers[idx] = fmt.Sprintf("127.0.0.1:%s", port) + clusterMembers[idx] = "127.0.0.1:" + port } caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) + username, _ := test.GenerateRandomString() password, _ := test.GenerateRandomString() htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) + resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() for _, port := range ports { @@ -1191,6 +1240,7 @@ func TestScaleOutRequestProxy(t *testing.T) { ctrlr := makeController(conf, t.TempDir()) cm := test.NewControllerManager(ctrlr) cm.StartAndWait(port) + defer cm.StopServer() } @@ -1222,10 +1272,12 @@ func TestScaleOutRequestProxy(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) result := common.ImageTags{} + err = json.Unmarshal(resp.Body(), &result) if err != nil { t.Fatalf("Failed to unmarshal") } + So(result.Name, ShouldEqual, repoName) So(len(result.Tags), ShouldEqual, 1) So(result.Tags[0], ShouldEqual, "1.0") @@ -1240,10 +1292,11 @@ func TestScaleOutRequestProxy(t *testing.T) { ports := make([]string, numMembers) clusterMembers := make([]string, numMembers) + for idx := 0; idx < numMembers; idx++ { port := test.GetFreePort() ports[idx] = port - clusterMembers[idx] = fmt.Sprintf("127.0.0.1:%s", port) + clusterMembers[idx] = "127.0.0.1:" + port } for _, port := range ports { @@ -1264,14 +1317,17 @@ func TestScaleOutRequestProxy(t *testing.T) { ctrlr := makeController(conf, t.TempDir()) cm := test.NewControllerManager(ctrlr) cm.StartAndWait(port) + defer cm.StopServer() } caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() Convey("Both controllers should start up and respond without error", func() { @@ -1298,10 +1354,11 @@ func TestScaleOutRequestProxy(t *testing.T) { ports := make([]string, numMembers) clusterMembers := make([]string, numMembers) + for idx := 0; idx < numMembers; idx++ { port := test.GetFreePort() ports[idx] = port - clusterMembers[idx] = fmt.Sprintf("127.0.0.1:%s", port) + clusterMembers[idx] = "127.0.0.1:" + port } for _, port := range ports { @@ -1321,16 +1378,20 @@ func TestScaleOutRequestProxy(t *testing.T) { } ctrlr := makeController(conf, t.TempDir()) + cm := test.NewControllerManager(ctrlr) cm.StartAndWait(port) + defer cm.StopServer() } caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() Convey("Both controllers should start up and respond without error", func() { @@ -1357,10 +1418,11 @@ func TestScaleOutRequestProxy(t *testing.T) { ports := make([]string, numMembers) clusterMembers := make([]string, numMembers) + for idx := 0; idx < numMembers; idx++ { port := test.GetFreePort() ports[idx] = port - clusterMembers[idx] = fmt.Sprintf("127.0.0.1:%s", port) + clusterMembers[idx] = "127.0.0.1:" + port } for _, port := range ports { @@ -1381,16 +1443,20 @@ func TestScaleOutRequestProxy(t *testing.T) { } ctrlr := makeController(conf, t.TempDir()) + cm := test.NewControllerManager(ctrlr) cm.StartAndWait(port) + defer cm.StopServer() } caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() Convey("Both controllers should start up and respond without error", func() { @@ -1422,13 +1488,16 @@ func TestPrintTracebackOnPanic(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // clean up ctlr := makeController(conf, t.TempDir()) cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() ctlr.StoreController.SubStore = make(map[string]storageTypes.ImageStore) @@ -1456,6 +1525,7 @@ func TestInterruptedBlobUpload(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() client := resty.New() @@ -1467,7 +1537,9 @@ func TestInterruptedBlobUpload(t *testing.T) { s1, seed1 := test.GenerateRandomName() s2, seed2 := test.GenerateRandomName() repoName := s1 + "/" + s2 + ctlr.Log.Info().Int64("seed1", seed1).Int64("seed2", seed2).Msg("random seeds for repoName") + resp, err := client.R().Post(baseURL + "/v2/" + repoName + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -1484,7 +1556,7 @@ func TestInterruptedBlobUpload(t *testing.T) { go func(ctx context.Context) { for i := 0; i < 3; i++ { _, _ = client.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). @@ -1521,7 +1593,9 @@ func TestInterruptedBlobUpload(t *testing.T) { s1, seed1 := test.GenerateRandomName() s2, seed2 := test.GenerateRandomName() repoName := s1 + "/" + s2 + ctlr.Log.Info().Int64("seed1", seed1).Int64("seed2", seed2).Msg("random seeds for repoName") + resp, err := client.R().Post(baseURL + "/v2/" + repoName + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -1538,7 +1612,7 @@ func TestInterruptedBlobUpload(t *testing.T) { go func(ctx context.Context) { for i := 0; i < 3; i++ { _, _ = client.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). @@ -1578,7 +1652,9 @@ func TestInterruptedBlobUpload(t *testing.T) { s1, seed1 := test.GenerateRandomName() s2, seed2 := test.GenerateRandomName() repoName := s1 + "/" + s2 + ctlr.Log.Info().Int64("seed1", seed1).Int64("seed2", seed2).Msg("random seeds for repoName") + resp, err := client.R().Post(baseURL + "/v2/" + repoName + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -1595,7 +1671,7 @@ func TestInterruptedBlobUpload(t *testing.T) { go func(ctx context.Context) { for i := 0; i < 3; i++ { _, _ = client.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). @@ -1632,7 +1708,9 @@ func TestInterruptedBlobUpload(t *testing.T) { s1, seed1 := test.GenerateRandomName() s2, seed2 := test.GenerateRandomName() repoName := s1 + "/" + s2 + ctlr.Log.Info().Int64("seed1", seed1).Int64("seed2", seed2).Msg("random seeds for repoName") + resp, err := client.R().Post(baseURL + "/v2/" + repoName + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -1649,7 +1727,7 @@ func TestInterruptedBlobUpload(t *testing.T) { go func(ctx context.Context) { for i := 0; i < 3; i++ { _, _ = client.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). @@ -1694,7 +1772,9 @@ func TestMultipleInstance(t *testing.T) { conf.HTTP.Port = port username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -1717,12 +1797,14 @@ func TestMultipleInstance(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() client := resty.New() tagResponse, err := client.R().SetBasicAuth(username, password). Get(baseURL + "/v2/zot-test/tags/list") + So(err, ShouldBeNil) So(tagResponse.StatusCode(), ShouldEqual, http.StatusNotFound) }) @@ -1734,7 +1816,9 @@ func TestMultipleInstance(t *testing.T) { conf.HTTP.Port = port username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -1746,11 +1830,13 @@ func TestMultipleInstance(t *testing.T) { subDir := t.TempDir() ctlr := makeController(conf, globalDir) ctlr.Log.Info().Int64("seedUser", seedUser).Int64("seedPass", seedPass).Msg("random seed for username & password") + subPathMap := make(map[string]config.StorageConfig) subPathMap["/a"] = config.StorageConfig{RootDirectory: subDir} cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // without creds, should get access error @@ -1758,7 +1844,9 @@ func TestMultipleInstance(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + var e apiErr.Error + err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) @@ -1778,7 +1866,9 @@ func TestMultipleInstance(t *testing.T) { conf.HTTP.Port = port username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -1791,6 +1881,7 @@ func TestMultipleInstance(t *testing.T) { ctlr := makeController(conf, globalDir) ctlr.Log.Info().Int64("seedUser", seedUser).Int64("seedPass", seedPass).Msg("random seed for username & password") + subPathMap := make(map[string]config.StorageConfig) subPathMap["/a"] = config.StorageConfig{RootDirectory: globalDir, Dedupe: true, GC: true} subPathMap["/b"] = config.StorageConfig{RootDirectory: subDir, Dedupe: true, GC: true} @@ -1823,11 +1914,15 @@ func TestTLSWithBasicAuth(t *testing.T) { Convey("Make a new controller", t, func() { caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) + username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) port := test.GetFreePort() @@ -1835,7 +1930,9 @@ func TestTLSWithBasicAuth(t *testing.T) { secureBaseURL := test.GetSecureBaseURL(port) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = port conf.HTTP.TLS = &config.TLSConfig{ @@ -1853,6 +1950,7 @@ func TestTLSWithBasicAuth(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // accessing insecure HTTP site should fail @@ -1866,7 +1964,9 @@ func TestTLSWithBasicAuth(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + var e apiErr.Error + err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) @@ -1885,11 +1985,15 @@ func TestTLSWithBasicAuthAllowReadAccess(t *testing.T) { Convey("Make a new controller", t, func() { caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) + username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) port := test.GetFreePort() @@ -1897,7 +2001,9 @@ func TestTLSWithBasicAuthAllowReadAccess(t *testing.T) { secureBaseURL := test.GetSecureBaseURL(port) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = port conf.HTTP.Auth = &config.AuthConfig{ @@ -1923,6 +2029,7 @@ func TestTLSWithBasicAuthAllowReadAccess(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // accessing insecure HTTP site should fail @@ -1956,6 +2063,7 @@ func TestMutualTLSAuthWithUserPermissions(t *testing.T) { Convey("Make a new controller", t, func() { caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) @@ -1964,7 +2072,9 @@ func TestMutualTLSAuthWithUserPermissions(t *testing.T) { secureBaseURL := test.GetSecureBaseURL(port) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = port @@ -1991,6 +2101,7 @@ func TestMutualTLSAuthWithUserPermissions(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() resp, err := resty.R().Get(baseURL) @@ -2005,6 +2116,7 @@ func TestMutualTLSAuthWithUserPermissions(t *testing.T) { So(err, ShouldBeNil) resty.SetCertificates(cert) + defer func() { resty.SetCertificates(tls.Certificate{}) }() // with client certs but without creds, should succeed @@ -2172,6 +2284,7 @@ func TestMutualTLSAuthWithoutCN(t *testing.T) { Convey("Make a new controller", t, func() { caCert, err := os.ReadFile("../../test/data/noidentity/ca.crt") So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) @@ -2179,7 +2292,9 @@ func TestMutualTLSAuthWithoutCN(t *testing.T) { secureBaseURL := test.GetSecureBaseURL(port) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = port @@ -2206,6 +2321,7 @@ func TestMutualTLSAuthWithoutCN(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // setup TLS mutual auth @@ -2213,6 +2329,7 @@ func TestMutualTLSAuthWithoutCN(t *testing.T) { So(err, ShouldBeNil) resty.SetCertificates(cert) + defer func() { resty.SetCertificates(tls.Certificate{}) }() // with client certs but without TLS mutual auth setup should get certificate error @@ -2225,6 +2342,7 @@ func TestTLSMutualAuth(t *testing.T) { Convey("Make a new controller", t, func() { caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) @@ -2233,7 +2351,9 @@ func TestTLSMutualAuth(t *testing.T) { secureBaseURL := test.GetSecureBaseURL(port) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = port conf.HTTP.TLS = &config.TLSConfig{ @@ -2246,6 +2366,7 @@ func TestTLSMutualAuth(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // accessing insecure HTTP site should fail @@ -2270,6 +2391,7 @@ func TestTLSMutualAuth(t *testing.T) { So(err, ShouldBeNil) resty.SetCertificates(cert) + defer func() { resty.SetCertificates(tls.Certificate{}) }() // with client certs but without creds, should succeed @@ -2310,6 +2432,7 @@ func TestTSLFailedReadingOfCACert(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() + ctlr := makeController(conf, t.TempDir()) err = ctlr.Init() @@ -2328,6 +2451,7 @@ func TestTSLFailedReadingOfCACert(t *testing.T) { So(err, ShouldNotBeNil) case <-ctx.Done(): testTimeout = true + cancel() } @@ -2350,6 +2474,7 @@ func TestTSLFailedReadingOfCACert(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() + ctlr := makeController(conf, t.TempDir()) err = ctlr.Init() @@ -2368,6 +2493,7 @@ func TestTSLFailedReadingOfCACert(t *testing.T) { So(err, ShouldNotBeNil) case <-ctx.Done(): testTimeout = true + cancel() } @@ -2379,6 +2505,7 @@ func TestTLSMutualAuthAllowReadAccess(t *testing.T) { Convey("Make a new controller", t, func() { caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) @@ -2387,7 +2514,9 @@ func TestTLSMutualAuthAllowReadAccess(t *testing.T) { secureBaseURL := test.GetSecureBaseURL(port) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = port conf.HTTP.TLS = &config.TLSConfig{ @@ -2408,6 +2537,7 @@ func TestTLSMutualAuthAllowReadAccess(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // accessing insecure HTTP site should fail @@ -2439,6 +2569,7 @@ func TestTLSMutualAuthAllowReadAccess(t *testing.T) { So(err, ShouldBeNil) resty.SetCertificates(cert) + defer func() { resty.SetCertificates(tls.Certificate{}) }() // with client certs but without creds, should succeed @@ -2463,11 +2594,15 @@ func TestTLSMutualAndBasicAuth(t *testing.T) { Convey("Make a new controller", t, func() { caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) + username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) port := test.GetFreePort() @@ -2475,7 +2610,9 @@ func TestTLSMutualAndBasicAuth(t *testing.T) { secureBaseURL := test.GetSecureBaseURL(port) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = port conf.HTTP.Auth = &config.AuthConfig{ @@ -2494,6 +2631,7 @@ func TestTLSMutualAndBasicAuth(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // accessing insecure HTTP site should fail @@ -2519,6 +2657,7 @@ func TestTLSMutualAndBasicAuth(t *testing.T) { So(err, ShouldBeNil) resty.SetCertificates(cert) + defer func() { resty.SetCertificates(tls.Certificate{}) }() // with client certs but without creds, should get access error @@ -2542,11 +2681,15 @@ func TestTLSMutualAndBasicAuthAllowReadAccess(t *testing.T) { Convey("Make a new controller", t, func() { caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) + username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) port := test.GetFreePort() @@ -2554,7 +2697,9 @@ func TestTLSMutualAndBasicAuthAllowReadAccess(t *testing.T) { secureBaseURL := test.GetSecureBaseURL(port) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = port conf.HTTP.Auth = &config.AuthConfig{ @@ -2581,6 +2726,7 @@ func TestTLSMutualAndBasicAuthAllowReadAccess(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // accessing insecure HTTP site should fail @@ -2606,6 +2752,7 @@ func TestTLSMutualAndBasicAuthAllowReadAccess(t *testing.T) { So(err, ShouldBeNil) resty.SetCertificates(cert) + defer func() { resty.SetCertificates(tls.Certificate{}) }() // with client certs but without creds, reads should succeed @@ -2732,12 +2879,13 @@ func (l *testLDAPServer) Search(boundDN string, req vldap.SearchRequest, func TestBasicAuthWithLDAP(t *testing.T) { Convey("Make a new controller", t, func() { - l := newTestLDAPServer() + ldapServer := newTestLDAPServer() port := test.GetFreePort() ldapPort, err := strconv.Atoi(port) So(err, ShouldBeNil) - l.Start(ldapPort) - defer l.Stop() + ldapServer.Start(ldapPort) + + defer ldapServer.Stop() port = test.GetFreePort() baseURL := test.GetBaseURL(port) @@ -2757,6 +2905,7 @@ func TestBasicAuthWithLDAP(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // without creds, should get access error @@ -2764,7 +2913,9 @@ func TestBasicAuthWithLDAP(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + var e apiErr.Error + err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) @@ -2790,6 +2941,7 @@ func TestBasicAuthWithReloadedCredentials(t *testing.T) { ldapPort, err := strconv.Atoi(test.GetFreePort()) So(err, ShouldBeNil) l.Start(ldapPort) + defer l.Stop() tempDir := t.TempDir() @@ -2879,6 +3031,7 @@ func TestBasicAuthWithReloadedCredentials(t *testing.T) { // test if the credentials don't work resp, _ = resty.R().SetBasicAuth(username, password).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) + if resp.StatusCode() == http.StatusOK { break } @@ -2922,6 +3075,7 @@ func TestBasicAuthWithReloadedCredentials(t *testing.T) { // test if the credentials don't work resp, _ = resty.R().SetBasicAuth(username, password).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) + if resp.StatusCode() == http.StatusOK { break } @@ -2950,6 +3104,7 @@ func TestBasicAuthWithReloadedCredentials(t *testing.T) { // test if the credentials don't work resp, _ = resty.R().SetBasicAuth(username, password).Get(baseURL + "/v2/") So(resp, ShouldNotBeNil) + if resp.StatusCode() == http.StatusOK { break } @@ -2963,12 +3118,13 @@ func TestBasicAuthWithReloadedCredentials(t *testing.T) { func TestLDAPWithoutCreds(t *testing.T) { Convey("Make a new LDAP server", t, func() { - l := newTestLDAPServer() + ldapServer := newTestLDAPServer() port := test.GetFreePort() ldapPort, err := strconv.Atoi(port) So(err, ShouldBeNil) - l.Start(ldapPort) - defer l.Stop() + ldapServer.Start(ldapPort) + + defer ldapServer.Stop() Convey("Server credentials succed ldap auth", func() { port = test.GetFreePort() @@ -2989,6 +3145,7 @@ func TestLDAPWithoutCreds(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // without creds, should get access error @@ -2996,7 +3153,9 @@ func TestLDAPWithoutCreds(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + var e apiErr.Error + err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) @@ -3032,6 +3191,7 @@ func TestLDAPWithoutCreds(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() resp, _ := resty.R().SetBasicAuth(username, password).Get(baseURL + "/v2/") @@ -3043,12 +3203,13 @@ func TestLDAPWithoutCreds(t *testing.T) { func TestBasicAuthWithLDAPFromFile(t *testing.T) { Convey("Make a new controller", t, func() { - l := newTestLDAPServer() + ldapServer := newTestLDAPServer() port := test.GetFreePort() ldapPort, err := strconv.Atoi(port) So(err, ShouldBeNil) - l.Start(ldapPort) - defer l.Stop() + ldapServer.Start(ldapPort) + + defer ldapServer.Stop() port = test.GetFreePort() baseURL := test.GetBaseURL(port) @@ -3094,6 +3255,7 @@ func TestBasicAuthWithLDAPFromFile(t *testing.T) { server := server.NewServerRootCmd() server.SetArgs([]string{"serve", configPath}) + go func() { err := server.Execute() if err != nil { @@ -3108,7 +3270,9 @@ func TestBasicAuthWithLDAPFromFile(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + var e apiErr.Error + err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) @@ -3250,12 +3414,13 @@ func TestLDAPConfigErrors(t *testing.T) { func TestGroupsPermissionsForLDAP(t *testing.T) { Convey("Make a new controller", t, func() { - l := newTestLDAPServer() + ldapServer := newTestLDAPServer() port := test.GetFreePort() ldapPort, err := strconv.Atoi(port) So(err, ShouldBeNil) - l.Start(ldapPort) - defer l.Stop() + ldapServer.Start(ldapPort) + + defer ldapServer.Stop() port = test.GetFreePort() baseURL := test.GetBaseURL(port) @@ -3303,6 +3468,7 @@ func TestGroupsPermissionsForLDAP(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() img := CreateDefaultImage() @@ -3316,12 +3482,13 @@ func TestGroupsPermissionsForLDAP(t *testing.T) { func TestLDAPConfigFromFile(t *testing.T) { Convey("Make a new controller", t, func() { - l := newTestLDAPServer() + ldapServer := newTestLDAPServer() port := test.GetFreePort() ldapPort, err := strconv.Atoi(port) So(err, ShouldBeNil) - l.Start(ldapPort) - defer l.Stop() + ldapServer.Start(ldapPort) + + defer ldapServer.Stop() port = test.GetFreePort() baseURL := test.GetBaseURL(port) @@ -3392,6 +3559,7 @@ func TestLDAPConfigFromFile(t *testing.T) { server := server.NewServerRootCmd() server.SetArgs([]string{"serve", configPath}) + go func() { err := server.Execute() if err != nil { @@ -3411,12 +3579,13 @@ func TestLDAPConfigFromFile(t *testing.T) { func TestLDAPFailures(t *testing.T) { Convey("Make a LDAP conn", t, func() { - l := newTestLDAPServer() + ldapServer := newTestLDAPServer() port := test.GetFreePort() ldapPort, err := strconv.Atoi(port) So(err, ShouldBeNil) - l.Start(ldapPort) - defer l.Stop() + ldapServer.Start(ldapPort) + + defer ldapServer.Stop() Convey("Empty config", func() { lc := &api.LDAPClient{} @@ -3447,12 +3616,13 @@ func TestLDAPFailures(t *testing.T) { func TestLDAPClient(t *testing.T) { Convey("LDAP Client", t, func() { - l := newTestLDAPServer() + ldapServer := newTestLDAPServer() port := test.GetFreePort() ldapPort, err := strconv.Atoi(port) So(err, ShouldBeNil) - l.Start(ldapPort) - defer l.Stop() + ldapServer.Start(ldapPort) + + defer ldapServer.Stop() // bad server credentials lClient := &api.LDAPClient{ @@ -3533,6 +3703,7 @@ func TestBearerAuth(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() blob := []byte("hello, blob!") @@ -3550,12 +3721,14 @@ func TestBearerAuth(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var goodToken authutils.AccessTokenResponse + err = json.Unmarshal(resp.Body(), &goodToken) So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3563,14 +3736,14 @@ func TestBearerAuth(t *testing.T) { // trigger decode error resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", "invalidToken")). + SetHeader("Authorization", "Bearer "+"invalidToken"). Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) resp, err = resty.R().SetHeader("Authorization", - fmt.Sprintf("Bearer %s", goodToken.AccessToken)).Options(baseURL + "/v2/") + "Bearer "+goodToken.AccessToken).Options(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNoContent) @@ -3578,7 +3751,9 @@ func TestBearerAuth(t *testing.T) { s1, seed1 := test.GenerateRandomName() s2, seed2 := test.GenerateRandomName() repoName := s1 + "/" + s2 + ctlr.Log.Info().Int64("seed1", seed1).Int64("seed2", seed2).Msg("random seeds for repoName") + resp, err = resty.R().Post(baseURL + "/v2/" + repoName + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3596,7 +3771,7 @@ func TestBearerAuth(t *testing.T) { So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Post(baseURL + "/v2/" + repoName + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3604,7 +3779,7 @@ func TestBearerAuth(t *testing.T) { loc := resp.Header().Get("Location") resp, err = resty.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). @@ -3625,9 +3800,9 @@ func TestBearerAuth(t *testing.T) { So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). SetQueryParam("digest", digest). SetBody(blob). Put(baseURL + loc) @@ -3636,7 +3811,7 @@ func TestBearerAuth(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusCreated) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(baseURL + "/v2/" + repoName + "/tags/list") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3654,7 +3829,7 @@ func TestBearerAuth(t *testing.T) { So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(baseURL + "/v2/" + repoName + "/tags/list") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3674,12 +3849,14 @@ func TestBearerAuth(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var badToken authutils.AccessTokenResponse + err = json.Unmarshal(resp.Body(), &badToken) So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", badToken.AccessToken)). + SetHeader("Authorization", "Bearer "+badToken.AccessToken). Post(baseURL + "/v2/" + UnauthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3741,6 +3918,7 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() blob := []byte("hello, blob!") @@ -3759,12 +3937,14 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var goodToken authutils.AccessTokenResponse + err = json.Unmarshal(resp.Body(), &goodToken) So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3773,7 +3953,9 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { s1, seed1 := test.GenerateRandomName() s2, seed2 := test.GenerateRandomName() repoName := s1 + "/" + s2 + ctlr.Log.Info().Int64("seed1", seed1).Int64("seed2", seed2).Msg("random seeds for repoName") + resp, err = resty.R().Post(baseURL + "/v2/" + repoName + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3791,7 +3973,7 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Post(baseURL + "/v2/" + repoName + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3799,7 +3981,7 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { loc := resp.Header().Get("Location") resp, err = resty.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). @@ -3820,9 +4002,9 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). SetQueryParam("digest", digest). SetBody(blob). Put(baseURL + loc) @@ -3831,7 +4013,7 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusCreated) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(baseURL + "/v2/" + repoName + "/tags/list") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3849,7 +4031,7 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(baseURL + "/v2/" + repoName + "/tags/list") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3869,12 +4051,13 @@ func TestBearerAuthWithAllowReadAccess(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var badToken authutils.AccessTokenResponse err = json.Unmarshal(resp.Body(), &badToken) So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", badToken.AccessToken)). + SetHeader("Authorization", "Bearer "+badToken.AccessToken). Post(baseURL + "/v2/" + UnauthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -3970,7 +4153,7 @@ func TestOpenIDMiddleware(t *testing.T) { }{ { address: "0.0.0.0", - externalURL: fmt.Sprintf("http://%s", net.JoinHostPort(conf.HTTP.Address, conf.HTTP.Port)), + externalURL: "http://" + net.JoinHostPort(conf.HTTP.Address, conf.HTTP.Port), testCaseName: "with ExternalURL provided in config", }, { @@ -4071,6 +4254,7 @@ func TestOpenIDMiddleware(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartServer() + defer cm.StopServer() test.WaitTillServerReady(baseURL) @@ -4219,7 +4403,9 @@ func TestOpenIDMiddleware(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + var e apiErr.Error + err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) @@ -4281,7 +4467,9 @@ func TestOpenIDMiddleware(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + var e apiErr.Error + err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) @@ -4401,6 +4589,7 @@ func TestIsOpenIDEnabled(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartServer() + defer cm.StopServer() test.WaitTillServerReady(baseURL) @@ -4434,6 +4623,7 @@ func TestIsOpenIDEnabled(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartServer() + defer cm.StopServer() test.WaitTillServerReady(baseURL) @@ -4461,7 +4651,9 @@ func TestAuthnSessionErrors(t *testing.T) { // need a username different than ldap one, to test both logic htpasswdUsername, seedUser := test.GenerateRandomString() htpasswdPassword, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(htpasswdUsername, htpasswdPassword)) + defer os.Remove(htpasswdPath) ldapServer := newTestLDAPServer() @@ -4535,6 +4727,7 @@ func TestAuthnSessionErrors(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartServer() + defer cm.StopServer() test.WaitTillServerReady(baseURL) @@ -4861,7 +5054,9 @@ func TestAuthnMetaDBErrors(t *testing.T) { username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) mockOIDCServer, err := authutils.MockOIDCRun() @@ -4904,6 +5099,7 @@ func TestAuthnMetaDBErrors(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartServer() + defer cm.StopServer() test.WaitTillServerReady(baseURL) @@ -4973,6 +5169,7 @@ func TestAuthorization(t *testing.T) { username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -5036,6 +5233,7 @@ func TestAuthorization(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() client := resty.New() @@ -5072,6 +5270,7 @@ func TestAuthorization(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() client := resty.New() @@ -5090,6 +5289,7 @@ func TestGetUsername(t *testing.T) { username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) conf := config.New() @@ -5106,6 +5306,7 @@ func TestGetUsername(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() resp, err := resty.R().Get(baseURL + "/v2/") @@ -5132,6 +5333,7 @@ func TestGetUsername(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) var e apiErr.Error + err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) @@ -5158,7 +5360,9 @@ func TestAuthorizationMountBlob(t *testing.T) { username2 = strings.ToLower(username2) content := test.GetCredString(username1, password1) + test.GetCredString(username2, password2) + htpasswdPath := test.MakeHtpasswdFileFromString(content) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -5167,8 +5371,8 @@ func TestAuthorizationMountBlob(t *testing.T) { }, } - user1Repo := fmt.Sprintf("%s/**", username1) - user2Repo := fmt.Sprintf("%s/**", username2) + user1Repo := username1 + "/**" + user2Repo := username2 + "/**" // config with all policy types, to test that the correct one is applied in each case conf.HTTP.AccessControl = &config.AccessControlConfig{ @@ -5205,6 +5409,7 @@ func TestAuthorizationMountBlob(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() userClient1 := resty.New() @@ -5261,6 +5466,7 @@ func TestAuthorizationMountBlob(t *testing.T) { func TestAuthorizationWithOnlyAnonymousPolicy(t *testing.T) { Convey("Make a new controller", t, func() { const TestRepo = "my-repos/repo" + port := test.GetFreePort() baseURL := test.GetBaseURL(port) @@ -5279,6 +5485,7 @@ func TestAuthorizationWithOnlyAnonymousPolicy(t *testing.T) { ctlr := makeController(conf, dir) cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() blob := []byte("hello, blob!") @@ -5293,7 +5500,9 @@ func TestAuthorizationWithOnlyAnonymousPolicy(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var e apiErr.Error + err = json.Unmarshal(resp.Body(), &e) So(err, ShouldBeNil) @@ -5316,7 +5525,7 @@ func TestAuthorizationWithOnlyAnonymousPolicy(t *testing.T) { loc := resp.Header().Get("Location") // uploading blob should get 201 - resp, err = resty.R().SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + resp, err = resty.R().SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). @@ -5334,7 +5543,7 @@ func TestAuthorizationWithOnlyAnonymousPolicy(t *testing.T) { loc = test.Location(baseURL, resp) // uploading blob should get 201 - resp, err = resty.R().SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + resp, err = resty.R().SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -5379,7 +5588,7 @@ func TestAuthorizationWithOnlyAnonymousPolicy(t *testing.T) { loc = test.Location(baseURL, resp) // uploading blob should get 201 resp, err = resty.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(updateBlob))). + SetHeader("Content-Length", strconv.Itoa(len(updateBlob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", string(godigest.FromBytes(updateBlob))). SetBody(updateBlob). @@ -5483,11 +5692,13 @@ func TestAuthorizationWithOnlyAnonymousPolicy(t *testing.T) { resp, err = resty.R().Get(baseURL + "/v2/_catalog") So(err, ShouldBeNil) + So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) err = json.Unmarshal(resp.Body(), &catalog) So(err, ShouldBeNil) + So(len(catalog.Repositories), ShouldEqual, 2) So(catalog.Repositories, ShouldContain, TestRepo) So(catalog.Repositories, ShouldContain, "zot-test") @@ -5497,7 +5708,9 @@ func TestAuthorizationWithOnlyAnonymousPolicy(t *testing.T) { func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) { Convey("Make a new controller", t, func() { const TestRepo = "my-repos/repo" + const AllRepos = "**" + port := test.GetFreePort() baseURL := test.GetBaseURL(port) @@ -5505,6 +5718,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) htpasswdUsername, seedUser := test.GenerateRandomString() htpasswdPassword, seedPass := test.GenerateRandomString() htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(htpasswdUsername, htpasswdPassword)) + defer os.Remove(htpasswdPath) img := CreateRandomImage() @@ -5538,6 +5752,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) ctlr.Log.Info().Int64("seedUser", seedUser).Int64("seedPass", seedPass).Msg("random seed for username & password") cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // /v2 access @@ -5574,7 +5789,9 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var apiError apiErr.Error + err = json.Unmarshal(resp.Body(), &apiError) So(err, ShouldBeNil) @@ -5584,6 +5801,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + apiError = apiErr.Error{} err = json.Unmarshal(resp.Body(), &apiError) So(err, ShouldBeNil) @@ -5593,6 +5811,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + apiError = apiErr.Error{} err = json.Unmarshal(resp.Body(), &apiError) So(err, ShouldBeNil) @@ -5603,6 +5822,7 @@ func TestAuthorizationWithAnonymousPolicyBasicAuthAndSessionHeader(t *testing.T) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusUnauthorized) + apiError = apiErr.Error{} err = json.Unmarshal(resp.Body(), &apiError) So(err, ShouldBeNil) @@ -5708,7 +5928,9 @@ func TestAuthorizationWithMultiplePolicies(t *testing.T) { username2, seedUser2 := test.GenerateRandomString() password2, seedPass2 := test.GenerateRandomString() content := test.GetCredString(username1, password1) + test.GetCredString(username2, password2) + htpasswdPath := test.MakeHtpasswdFileFromString(content) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -5771,6 +5993,7 @@ func TestAuthorizationWithMultiplePolicies(t *testing.T) { Msg("random seed for username & password") ctlr.Log.Info().Int64("seedUser2", seedUser2).Int64("seedPass2", seedPass2). Msg("random seed for username & password") + ctlr.Config.Storage.RootDirectory = dir err = WriteImageToFileSystem(CreateDefaultImage(), "zot-test", "0.0.1", @@ -5779,6 +6002,7 @@ func TestAuthorizationWithMultiplePolicies(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() testUserClient := resty.New() @@ -5838,6 +6062,7 @@ func TestAuthorizationWithMultiplePolicies(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() userClient1 := resty.New() @@ -5860,7 +6085,9 @@ func TestInvalidCases(t *testing.T) { conf.HTTP.Port = port username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -5950,6 +6177,7 @@ func TestHTTPReadOnly(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // with creds, should get expected status code @@ -5959,9 +6187,12 @@ func TestHTTPReadOnly(t *testing.T) { s1, seed1 := test.GenerateRandomName() s2, seed2 := test.GenerateRandomName() + repoName := s1 + "/" + s2 + ctlr.Log.Info().Int64("seed1", seed1).Int64("seed2", seed2).Msg("random seeds for repoName") // with creds, any modifications should still fail on read-only mode + resp, err := resty.R().SetBasicAuth(user, password). Post(baseURL + "/v2/" + repoName + "/blobs/uploads/") So(err, ShouldBeNil) @@ -5987,6 +6218,7 @@ func TestCrossRepoMount(t *testing.T) { username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -6122,6 +6354,7 @@ func TestCrossRepoMount(t *testing.T) { ctlr.Config.Storage.RootDirectory = newDir cm = test.NewControllerManager(ctlr) //nolint: varnamelen cm.StartAndWait(port) + defer cm.StopServer() // wait for dedupe task to run @@ -6222,6 +6455,7 @@ func TestCrossRepoMount(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // digest := test.GetTestBlobDigest("zot-cve-test", "layer").String() @@ -6369,10 +6603,14 @@ func TestParallelRequests(t *testing.T) { testImagesController := ociutils.GetDefaultStoreController(testImagesDir, ctlr.Log) err := WriteImageToFileSystem(CreateRandomImage(), "zot-test", "0.0.1", testImagesController) - assert.Equal(t, err, nil, "Error should be nil") + if err != nil { + t.Errorf("Error should be nil: %v", err) + } err = WriteImageToFileSystem(CreateRandomImage(), "zot-cve-test", "0.0.1", testImagesController) - assert.Equal(t, err, nil, "Error should be nil") + if err != nil { + t.Errorf("Error should be nil: %v", err) + } cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) @@ -6384,25 +6622,26 @@ func TestParallelRequests(t *testing.T) { t.Run(testcase.testCaseName, func(t *testing.T) { t.Parallel() + client := resty.New() tagResponse, err := client.R().SetBasicAuth(username, password). Get(baseURL + "/v2/" + testcase.destImageName + "/tags/list") - assert.Equal(t, err, nil, "Error should be nil") - assert.NotEqual(t, tagResponse.StatusCode(), http.StatusBadRequest, "bad request") + require.NoError(t, err, "Error should be nil") + assert.NotEqual(t, http.StatusBadRequest, tagResponse.StatusCode(), "bad request") manifestList := getAllManifests(path.Join(testImagesDir, testcase.srcImageName)) for _, manifest := range manifestList { headResponse, err := client.R().SetBasicAuth(username, password). Head(baseURL + "/v2/" + testcase.destImageName + "/manifests/" + manifest) - assert.Equal(t, err, nil, "Error should be nil") - assert.Equal(t, headResponse.StatusCode(), http.StatusNotFound, "response status code should return 404") + require.NoError(t, err, "Error should be nil") + assert.Equal(t, http.StatusNotFound, headResponse.StatusCode(), "response status code should return 404") getResponse, err := client.R().SetBasicAuth(username, password). Get(baseURL + "/v2/" + testcase.destImageName + "/manifests/" + manifest) - assert.Equal(t, err, nil, "Error should be nil") - assert.Equal(t, getResponse.StatusCode(), http.StatusNotFound, "response status code should return 404") + require.NoError(t, err, "Error should be nil") + assert.Equal(t, http.StatusNotFound, getResponse.StatusCode(), "response status code should return 404") } blobList := getAllBlobs(path.Join(testImagesDir, testcase.srcImageName)) @@ -6412,15 +6651,15 @@ func TestParallelRequests(t *testing.T) { headResponse, err := client.R().SetBasicAuth(username, password). Head(baseURL + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob) - assert.Equal(t, err, nil, "Should not be nil") - assert.NotEqual(t, headResponse.StatusCode(), http.StatusInternalServerError, + require.NoError(t, err, "Error should be nil") + assert.NotEqual(t, http.StatusInternalServerError, headResponse.StatusCode(), "internal server error should not occurred") getResponse, err := client.R().SetBasicAuth(username, password). Get(baseURL + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob) - assert.Equal(t, err, nil, "Should not be nil") - assert.NotEqual(t, getResponse.StatusCode(), http.StatusInternalServerError, + require.NoError(t, err, "Error should be nil") + assert.NotEqual(t, http.StatusInternalServerError, getResponse.StatusCode(), "internal server error should not occurred") blobPath := path.Join(testImagesDir, testcase.srcImageName, "blobs/sha256", blob) @@ -6436,8 +6675,8 @@ func TestParallelRequests(t *testing.T) { SetBasicAuth(username, password). SetBody(buf).Post(baseURL + "/v2/" + testcase.destImageName + "/blobs/uploads/") - assert.Equal(t, err, nil, "Error should be nil") - assert.NotEqual(t, postResponse.StatusCode(), http.StatusInternalServerError, + require.NoError(t, err, "Error should be nil") + assert.NotEqual(t, http.StatusInternalServerError, postResponse.StatusCode(), "response status code should not return 500") // Post request with query parameter @@ -6448,12 +6687,13 @@ func TestParallelRequests(t *testing.T) { SetBody(buf). Post(baseURL + "/v2/" + testcase.destImageName + "/blobs/uploads/") - assert.Equal(t, err, nil, "Error should be nil") - assert.NotEqual(t, postResponse.StatusCode(), http.StatusInternalServerError, + require.NoError(t, err, "Error should be nil") + assert.NotEqual(t, http.StatusInternalServerError, postResponse.StatusCode(), "response status code should not return 500") var sessionID string - sessionIDList := postResponse.Header().Values("Blob-Upload-UUID") + + sessionIDList := postResponse.Header().Values("Blob-Upload-UUID") //nolint:canonicalheader if len(sessionIDList) == 0 { location := postResponse.Header().Values("Location") firstLocation := location[0] @@ -6476,12 +6716,14 @@ func TestParallelRequests(t *testing.T) { if run%4 == 0 { readContent := 0 + for { nbytes, err := reader.Read(buf) if err != nil { if goerrors.Is(err, io.EOF) { break } + panic(err) } // Patch request of blob @@ -6489,13 +6731,13 @@ func TestParallelRequests(t *testing.T) { patchResponse, err := client.R(). SetBody(buf[0:nbytes]). SetHeader("Content-Type", "application/octet-stream"). - SetHeader("Content-Length", fmt.Sprintf("%d", nbytes)). - SetHeader("Content-Range", fmt.Sprintf("%d", readContent)+"-"+fmt.Sprintf("%d", readContent+nbytes-1)). + SetHeader("Content-Length", strconv.Itoa(nbytes)). + SetHeader("Content-Range", strconv.Itoa(readContent)+"-"+strconv.Itoa(readContent+nbytes-1)). SetBasicAuth(username, password). Patch(baseURL + "/v2/" + testcase.destImageName + "/blobs/uploads/" + sessionID) - assert.Equal(t, err, nil, "Error should be nil") - assert.NotEqual(t, patchResponse.StatusCode(), http.StatusInternalServerError, + require.NoError(t, err, "Error should be nil") + assert.NotEqual(t, http.StatusInternalServerError, patchResponse.StatusCode(), "response status code should not return 500") readContent += nbytes @@ -6507,6 +6749,7 @@ func TestParallelRequests(t *testing.T) { if goerrors.Is(err, io.EOF) { break } + panic(err) } // Patch request of blob @@ -6518,8 +6761,8 @@ func TestParallelRequests(t *testing.T) { panic(err) } - assert.Equal(t, err, nil, "Error should be nil") - assert.NotEqual(t, patchResponse.StatusCode(), http.StatusInternalServerError, + require.NoError(t, err, "Error should be nil") + assert.NotEqual(t, http.StatusInternalServerError, patchResponse.StatusCode(), "response status code should not return 500") } } @@ -6530,8 +6773,8 @@ func TestParallelRequests(t *testing.T) { SetBody(buf).SetQueryParam("digest", "sha256:"+blob). Post(baseURL + "/v2/" + testcase.destImageName + "/blobs/uploads/") - assert.Equal(t, err, nil, "Error should be nil") - assert.NotEqual(t, postResponse.StatusCode(), http.StatusInternalServerError, + require.NoError(t, err, "Error should be nil") + assert.NotEqual(t, http.StatusInternalServerError, postResponse.StatusCode(), "response status code should not return 500") } @@ -6539,26 +6782,26 @@ func TestParallelRequests(t *testing.T) { SetBasicAuth(username, password). Head(baseURL + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob) - assert.Equal(t, err, nil, "Should not be nil") - assert.NotEqual(t, headResponse.StatusCode(), http.StatusInternalServerError, "response should return success code") + require.NoError(t, err, "Error should be nil") + assert.NotEqual(t, http.StatusInternalServerError, headResponse.StatusCode(), "response should return success code") getResponse, err = client.R(). SetBasicAuth(username, password). Get(baseURL + "/v2/" + testcase.destImageName + "/blobs/sha256:" + blob) - assert.Equal(t, err, nil, "Should not be nil") - assert.NotEqual(t, getResponse.StatusCode(), http.StatusInternalServerError, "response should return success code") + require.NoError(t, err, "Error should be nil") + assert.NotEqual(t, http.StatusInternalServerError, getResponse.StatusCode(), "response should return success code") } tagResponse, err = client.R().SetBasicAuth(username, password). Get(baseURL + "/v2/" + testcase.destImageName + "/tags/list") - assert.Equal(t, err, nil, "Error should be nil") - assert.Equal(t, tagResponse.StatusCode(), http.StatusOK, "response status code should return success code") + require.NoError(t, err, "Error should be nil") + assert.Equal(t, http.StatusOK, tagResponse.StatusCode(), "response status code should return success code") repoResponse, err := client.R().SetBasicAuth(username, password). Get(baseURL + constants.RoutePrefix + constants.ExtCatalogPrefix) - assert.Equal(t, err, nil, "Error should be nil") - assert.Equal(t, repoResponse.StatusCode(), http.StatusOK, "response status code should return success code") + require.NoError(t, err, "Error should be nil") + assert.Equal(t, http.StatusOK, repoResponse.StatusCode(), "response status code should return success code") }) } } @@ -6592,6 +6835,7 @@ func TestHardLink(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() err = os.Chmod(dir, 0o644) @@ -6622,6 +6866,7 @@ func TestImageSignatures(t *testing.T) { cm := test.NewControllerManager(ctlr) // this blocks cm.StartAndWait(port) + defer cm.StopServer() repoName := "signed-repo" @@ -6635,12 +6880,15 @@ func TestImageSignatures(t *testing.T) { Convey("Validate cosign signatures", func() { cwd, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(cwd) }() + tdir := t.TempDir() _ = os.Chdir(tdir) // generate a keypair os.Setenv("COSIGN_PASSWORD", "") + err = generate.GenerateKeyPairCmd(context.TODO(), "", "cosign", nil) So(err, ShouldBeNil) @@ -6661,6 +6909,7 @@ func TestImageSignatures(t *testing.T) { aopts := &options.AnnotationOptions{Annotations: annotations} amap, err := aopts.AnnotationsMap() So(err, ShouldBeNil) + vrfy := verify.VerifyCommand{ RegistryOptions: options.RegistryOptions{AllowInsecure: true}, CheckClaims: true, @@ -6675,6 +6924,7 @@ func TestImageSignatures(t *testing.T) { aopts = &options.AnnotationOptions{Annotations: []string{"tag=2.0"}} amap, err = aopts.AnnotationsMap() So(err, ShouldBeNil) + vrfy = verify.VerifyCommand{ RegistryOptions: options.RegistryOptions{AllowInsecure: true}, CheckClaims: true, @@ -6689,6 +6939,7 @@ func TestImageSignatures(t *testing.T) { aopts = &options.AnnotationOptions{Annotations: []string{"tag=1.0"}} amap, err = aopts.AnnotationsMap() So(err, ShouldBeNil) + vrfy = verify.VerifyCommand{ CheckClaims: true, RegistryOptions: options.RegistryOptions{AllowInsecure: true}, @@ -6706,6 +6957,7 @@ func TestImageSignatures(t *testing.T) { So(err, ShouldBeNil) os.Setenv("COSIGN_PASSWORD", "") + err = generate.GenerateKeyPairCmd(context.TODO(), "", "cosign", nil) So(err, ShouldBeNil) @@ -6713,6 +6965,7 @@ func TestImageSignatures(t *testing.T) { aopts = &options.AnnotationOptions{Annotations: []string{"tag=1.0"}} amap, err = aopts.AnnotationsMap() So(err, ShouldBeNil) + vrfy = verify.VerifyCommand{ CheckClaims: true, RegistryOptions: options.RegistryOptions{AllowInsecure: true}, @@ -6727,7 +6980,9 @@ func TestImageSignatures(t *testing.T) { Convey("Validate notation signatures", func() { cwd, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(cwd) }() + tdir := t.TempDir() _ = os.Chdir(tdir) @@ -6763,6 +7018,7 @@ func TestImageSignatures(t *testing.T) { // check invalid content with artifact media type resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageManifest). SetBody([]byte("bogus")).Put(baseURL + fmt.Sprintf("/v2/%s/manifests/1.0", repoName)) + So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) @@ -6772,7 +7028,9 @@ func TestImageSignatures(t *testing.T) { fmt.Sprintf("%s/v2/%s/referrers/%s", baseURL, repoName, digest.String())) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var refs ispec.Index + err = json.Unmarshal(resp.Body(), &refs) So(err, ShouldBeNil) So(len(refs.Manifests), ShouldEqual, 1) @@ -6794,6 +7052,7 @@ func TestImageSignatures(t *testing.T) { fmt.Sprintf("%s/v2/%s/referrers/%s", baseURL, repoName, digest.String())) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var refs ispec.Index err = json.Unmarshal(resp.Body(), &refs) So(err, ShouldBeNil) @@ -6828,6 +7087,7 @@ func TestManifestValidation(t *testing.T) { // this blocks cm.StartServer() time.Sleep(1000 * time.Millisecond) + defer cm.StopServer() repoName := "validation" @@ -7048,6 +7308,7 @@ func TestArtifactReferences(t *testing.T) { // this blocks cm.StartServer() time.Sleep(1000 * time.Millisecond) + defer cm.StopServer() repoName := "artifact-repo" @@ -7081,7 +7342,7 @@ func TestArtifactReferences(t *testing.T) { resp, err = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -7180,7 +7441,7 @@ func TestArtifactReferences(t *testing.T) { resp, err = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -7199,6 +7460,7 @@ func TestArtifactReferences(t *testing.T) { manifest.SchemaVersion = 2 mcontent, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(mcontent) So(digest, ShouldNotBeNil) @@ -7267,7 +7529,7 @@ func TestArtifactReferences(t *testing.T) { So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) So(resp.Header().Get("Content-Type"), ShouldEqual, ispec.MediaTypeImageIndex) - So(resp.Header().Get("OCI-Filters-Applied"), ShouldEqual, "artifactType") + So(resp.Header().Get("OCI-Filters-Applied"), ShouldEqual, "artifactType") //nolint:canonicalheader resp, err = resty.R().SetQueryParams(map[string]string{"artifactType": artifactType + ",otherArtType"}).Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, @@ -7275,7 +7537,7 @@ func TestArtifactReferences(t *testing.T) { So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) So(resp.Header().Get("Content-Type"), ShouldEqual, ispec.MediaTypeImageIndex) - So(resp.Header().Get("OCI-Filters-Applied"), ShouldEqual, "artifactType") + So(resp.Header().Get("OCI-Filters-Applied"), ShouldEqual, "artifactType") //nolint:canonicalheader }) }) }) @@ -7294,6 +7556,7 @@ func TestRouteFailures(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() rthdlr := api.NewRouteHandler(ctlr) @@ -7304,6 +7567,7 @@ func TestRouteFailures(t *testing.T) { Convey("List tags", func() { request, _ := http.NewRequestWithContext(context.TODO(), http.MethodGet, baseURL, nil) mux.SetURLVars(request, map[string]string{}) + response := httptest.NewRecorder() rthdlr.ListTags(response, request) @@ -8048,6 +8312,7 @@ func TestStorageCommit(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() Convey("Manifests", func() { @@ -8071,6 +8336,7 @@ func TestStorageCommit(t *testing.T) { content := image.ManifestDescriptor.Data digest := image.ManifestDescriptor.Digest So(digest, ShouldNotBeNil) + resp, err = resty.R().SetHeader("Content-Type", "application/vnd.oci.image.manifest.v1+json"). SetBody(content).Put(baseURL + "/v2/repo7/manifests/test:1.0") So(err, ShouldBeNil) @@ -8178,6 +8444,7 @@ func TestManifestImageIndex(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() rthdlr := api.NewRouteHandler(ctlr) @@ -8200,6 +8467,7 @@ func TestManifestImageIndex(t *testing.T) { content := img.ManifestDescriptor.Data digest := img.ManifestDescriptor.Digest So(digest, ShouldNotBeNil) + m1content := content resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageManifest). SetBody(content).Put(baseURL + "/v2/index/manifests/test:1.0") @@ -8244,7 +8512,7 @@ func TestManifestImageIndex(t *testing.T) { digest = img.ManifestDescriptor.Digest resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageManifest). - SetBody(content).Put(baseURL + fmt.Sprintf("/v2/index/manifests/%s", digest.String())) + SetBody(content).Put(baseURL + "/v2/index/manifests/" + digest.String()) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusCreated) digestHdr := resp.Header().Get(constants.DistContentDigestKey) @@ -8268,6 +8536,7 @@ func TestManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) index1dgst := digest @@ -8278,6 +8547,7 @@ func TestManifestImageIndex(t *testing.T) { digestHdr = resp.Header().Get(constants.DistContentDigestKey) So(digestHdr, ShouldNotBeEmpty) So(digestHdr, ShouldEqual, digest.String()) + resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageIndex). Get(baseURL + "/v2/index/manifests/test:index1") So(err, ShouldBeNil) @@ -8296,7 +8566,7 @@ func TestManifestImageIndex(t *testing.T) { m4dgst := digest m4size := len(content) resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageManifest). - SetBody(content).Put(baseURL + fmt.Sprintf("/v2/index/manifests/%s", digest.String())) + SetBody(content).Put(baseURL + "/v2/index/manifests/" + digest.String()) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusCreated) digestHdr = resp.Header().Get(constants.DistContentDigestKey) @@ -8319,8 +8589,10 @@ func TestManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) + resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageIndex). SetBody(content).Put(baseURL + "/v2/index/manifests/test:index2") So(err, ShouldBeNil) @@ -8328,6 +8600,7 @@ func TestManifestImageIndex(t *testing.T) { digestHdr = resp.Header().Get(constants.DistContentDigestKey) So(digestHdr, ShouldNotBeEmpty) So(digestHdr, ShouldEqual, digest.String()) + resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageIndex). Get(baseURL + "/v2/index/manifests/test:index2") So(err, ShouldBeNil) @@ -8369,8 +8642,10 @@ func TestManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) + resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageIndex). SetBody(content).Put(baseURL + "/v2/index/manifests/test:index3") So(err, ShouldBeNil) @@ -8393,6 +8668,7 @@ func TestManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageIndex). @@ -8405,7 +8681,7 @@ func TestManifestImageIndex(t *testing.T) { }) Convey("Deleting manifest contained by a multiarch image should not be allowed", func() { - resp, err = resty.R().Delete(baseURL + fmt.Sprintf("/v2/index/manifests/%s", m2dgst.String())) + resp, err = resty.R().Delete(baseURL + "/v2/index/manifests/" + m2dgst.String()) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusMethodNotAllowed) }) @@ -8486,8 +8762,10 @@ func TestManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) + resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageIndex). SetBody(content).Put(baseURL + "/v2/index/manifests/test:index1") So(err, ShouldBeNil) @@ -8495,6 +8773,7 @@ func TestManifestImageIndex(t *testing.T) { digestHdr = resp.Header().Get(constants.DistContentDigestKey) So(digestHdr, ShouldNotBeEmpty) So(digestHdr, ShouldEqual, digest.String()) + resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageIndex). Get(baseURL + "/v2/index/manifests/test:index1") So(err, ShouldBeNil) @@ -8553,8 +8832,10 @@ func TestManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) + resp, err = resty.R().SetHeader("Content-Type", ispec.MediaTypeImageIndex). SetBody(content).Put(baseURL + "/v2/index/manifests/test:1.0") So(err, ShouldBeNil) @@ -8596,6 +8877,7 @@ func TestManifestCollision(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() img := CreateImageWith().RandomLayers(1, 2).DefaultConfig().Build() @@ -8654,6 +8936,7 @@ func TestPullRange(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // create a blob/layer @@ -8671,6 +8954,7 @@ func TestPullRange(t *testing.T) { resp, err = resty.R().Get(loc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNoContent) + content := []byte("0123456789") digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) @@ -8683,6 +8967,7 @@ func TestPullRange(t *testing.T) { So(blobLoc, ShouldNotBeEmpty) So(resp.Header().Get("Content-Length"), ShouldEqual, "0") So(resp.Header().Get(constants.DistContentDigestKey), ShouldNotBeEmpty) + blobLoc = baseURL + blobLoc Convey("Range is supported using 'bytes'", func() { @@ -8696,19 +8981,19 @@ func TestPullRange(t *testing.T) { resp, err = resty.R().SetHeader("Range", "bytes=0-").Get(blobLoc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusPartialContent) - So(resp.Header().Get("Content-Length"), ShouldEqual, fmt.Sprintf("%d", len(content))) + So(resp.Header().Get("Content-Length"), ShouldEqual, strconv.Itoa(len(content))) So(resp.Body(), ShouldResemble, content) resp, err = resty.R().SetHeader("Range", "bytes=0-100").Get(blobLoc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusPartialContent) - So(resp.Header().Get("Content-Length"), ShouldEqual, fmt.Sprintf("%d", len(content))) + So(resp.Header().Get("Content-Length"), ShouldEqual, strconv.Itoa(len(content))) So(resp.Body(), ShouldResemble, content) resp, err = resty.R().SetHeader("Range", "bytes=0-10").Get(blobLoc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusPartialContent) - So(resp.Header().Get("Content-Length"), ShouldEqual, fmt.Sprintf("%d", len(content))) + So(resp.Header().Get("Content-Length"), ShouldEqual, strconv.Itoa(len(content))) So(resp.Body(), ShouldResemble, content) resp, err = resty.R().SetHeader("Range", "bytes=0-0").Get(blobLoc) @@ -8814,6 +9099,7 @@ func TestInjectInterruptedImageManifest(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() rthdlr := api.NewRouteHandler(ctlr) @@ -8834,6 +9120,7 @@ func TestInjectInterruptedImageManifest(t *testing.T) { resp, err = resty.R().Get(loc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNoContent) + content := []byte("this is a dummy blob") digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) @@ -8856,7 +9143,7 @@ func TestInjectInterruptedImageManifest(t *testing.T) { resp, err = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -8882,6 +9169,7 @@ func TestInjectInterruptedImageManifest(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) @@ -8892,6 +9180,7 @@ func TestInjectInterruptedImageManifest(t *testing.T) { request, _ := http.NewRequestWithContext(context.TODO(), http.MethodPut, baseURL, bytes.NewReader(content)) request = mux.SetURLVars(request, map[string]string{"name": "repotest", "reference": "1.0"}) request.Header.Set("Content-Type", "application/vnd.oci.image.manifest.v1+json") + response := httptest.NewRecorder() rthdlr.UpdateManifest(response, request) @@ -8924,6 +9213,7 @@ func TestInjectTooManyOpenFiles(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() rthdlr := api.NewRouteHandler(ctlr) @@ -8943,6 +9233,7 @@ func TestInjectTooManyOpenFiles(t *testing.T) { resp, err = resty.R().Get(loc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNoContent) + content := []byte("this is a dummy blob") digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) @@ -8957,7 +9248,8 @@ func TestInjectTooManyOpenFiles(t *testing.T) { q.Add("digest", digest.String()) request.URL.RawQuery = q.Encode() request.Header.Set("Content-Type", "application/octet-stream") - request.Header.Set("Content-Length", fmt.Sprintf("%d", len(content))) + request.Header.Set("Content-Length", strconv.Itoa(len(content))) + response := httptest.NewRecorder() rthdlr.UpdateBlobUpload(response, request) @@ -8989,7 +9281,7 @@ func TestInjectTooManyOpenFiles(t *testing.T) { resp, err = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -9015,6 +9307,7 @@ func TestInjectTooManyOpenFiles(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) @@ -9026,6 +9319,7 @@ func TestInjectTooManyOpenFiles(t *testing.T) { request, _ := http.NewRequestWithContext(context.TODO(), http.MethodPut, baseURL, bytes.NewReader(content)) request = mux.SetURLVars(request, map[string]string{"name": "repotest", "reference": "1.0"}) request.Header.Set("Content-Type", "application/vnd.oci.image.manifest.v1+json") + response := httptest.NewRecorder() rthdlr.UpdateManifest(response, request) @@ -9046,6 +9340,7 @@ func TestInjectTooManyOpenFiles(t *testing.T) { request, _ := http.NewRequestWithContext(context.TODO(), http.MethodPut, baseURL, bytes.NewReader(content)) request = mux.SetURLVars(request, map[string]string{"name": "repotest", "reference": "1.0"}) request.Header.Set("Content-Type", "application/vnd.oci.image.manifest.v1+json") + response := httptest.NewRecorder() rthdlr.UpdateManifest(response, request) @@ -9067,6 +9362,7 @@ func TestInjectTooManyOpenFiles(t *testing.T) { request, _ := http.NewRequestWithContext(context.TODO(), http.MethodPut, baseURL, bytes.NewReader(content)) request = mux.SetURLVars(request, map[string]string{"name": "repotest", "reference": "1.0"}) request.Header.Set("Content-Type", "application/vnd.oci.image.manifest.v1+json") + response := httptest.NewRecorder() rthdlr.UpdateManifest(response, request) @@ -9095,6 +9391,7 @@ func TestInjectTooManyOpenFiles(t *testing.T) { indexFile := path.Join(dir, "repotest", "index.json") _, err = os.Stat(indexFile) So(err, ShouldBeNil) + indexContent := []byte(`not a JSON content`) err = os.WriteFile(indexFile, indexContent, 0o600) So(err, ShouldBeNil) @@ -9164,6 +9461,7 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartServer() //nolint: contextcheck cm.WaitServerToBeReady(port) + defer cm.StopServer() img := CreateDefaultImage() @@ -9185,18 +9483,21 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) { cwd, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(cwd) }() + tdir := t.TempDir() _ = os.Chdir(tdir) // generate a keypair os.Setenv("COSIGN_PASSWORD", "") + err = generate.GenerateKeyPairCmd(ctx, "", "cosign", nil) So(err, ShouldBeNil) image := fmt.Sprintf("localhost:%s/%s@%s", port, repoName, digest.String()) - annotations := []string{fmt.Sprintf("tag=%s", tag)} + annotations := []string{"tag=" + tag} // sign the image err = sign.SignCmd(&options.RootOptions{Verbose: true, Timeout: 1 * time.Minute}, @@ -9439,6 +9740,7 @@ func TestGCSignaturesAndUntaggedManifestsWithMetaDB(t *testing.T) { content, err := json.Marshal(index) So(err, ShouldBeNil) + indexDigest := godigest.FromBytes(content) So(indexDigest, ShouldNotBeNil) @@ -9480,7 +9782,9 @@ func TestPeriodicGC(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // clean up ctlr := api.NewController(conf) @@ -9497,6 +9801,7 @@ func TestPeriodicGC(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() time.Sleep(5000 * time.Millisecond) @@ -9506,9 +9811,9 @@ func TestPeriodicGC(t *testing.T) { So(string(data), ShouldContainSubstring, "\"GC\":true,\"Commit\":false,\"GCDelay\":1000000000,\"GCInterval\":3600000000000") So(string(data), ShouldContainSubstring, - fmt.Sprintf("executing GC of orphaned blobs for %s", path.Join(ctlr.StoreController.DefaultStore.RootDir(), repoName))) //nolint:lll + "executing gc of orphaned blobs for "+path.Join(ctlr.StoreController.DefaultStore.RootDir(), repoName)) //nolint:lll So(string(data), ShouldContainSubstring, - fmt.Sprintf("GC successfully completed for %s", path.Join(ctlr.StoreController.DefaultStore.RootDir(), repoName))) //nolint:lll + "gc successfully completed for "+path.Join(ctlr.StoreController.DefaultStore.RootDir(), repoName)) //nolint:lll }) Convey("Periodic GC enabled for substore", t, func() { @@ -9518,7 +9823,9 @@ func TestPeriodicGC(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // clean up dir := t.TempDir() @@ -9540,13 +9847,16 @@ func TestPeriodicGC(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() data, err := os.ReadFile(logFile.Name()) So(err, ShouldBeNil) + // periodic GC is enabled by default for default store with a default interval So(string(data), ShouldContainSubstring, "\"GCDelay\":3600000000000,\"GCInterval\":3600000000000,\"") + // periodic GC is enabled for sub store So(string(data), ShouldContainSubstring, fmt.Sprintf("\"SubPaths\":{\"/a\":{\"RootDirectory\":\"%s\",\"Dedupe\":false,\"RemoteCache\":false,\"GC\":true,\"Commit\":false,\"GCDelay\":1000000000,\"GCInterval\":86400000000000", subDir)) //nolint:lll // gofumpt conflicts with lll @@ -9562,7 +9872,9 @@ func TestPeriodicGC(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // clean up ctlr := api.NewController(conf) @@ -9586,6 +9898,7 @@ func TestPeriodicGC(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() time.Sleep(5000 * time.Millisecond) @@ -9612,8 +9925,11 @@ func TestSearchRoutes(t *testing.T) { user1 := "test" password1 := "test" testString1 := test.GetCredString(user1, password1) + htpasswdPath := test.MakeHtpasswdFileFromString(testString1) + defer os.Remove(htpasswdPath) + conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ Path: htpasswdPath, @@ -9663,6 +9979,7 @@ func TestSearchRoutes(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() img := CreateImageWith().RandomLayers(1, 10000).DefaultConfig().Build() @@ -9751,8 +10068,11 @@ func TestSearchRoutes(t *testing.T) { password1 := "test1" group1 := "testgroup3" testString1 := test.GetCredString(user1, password1) + htpasswdPath := test.MakeHtpasswdFileFromString(testString1) + defer os.Remove(htpasswdPath) + conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ Path: htpasswdPath, @@ -9798,6 +10118,7 @@ func TestSearchRoutes(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() img := CreateRandomImage() @@ -9819,6 +10140,7 @@ func TestSearchRoutes(t *testing.T) { }` resp, err := resty.R().SetBasicAuth(user1, password1).Get(baseURL + constants.FullSearchPrefix + "?query=" + url.QueryEscape(query)) + So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 200) @@ -9835,6 +10157,7 @@ func TestSearchRoutes(t *testing.T) { group2 := "secondtestgroup" testString1 := test.GetCredString(user1, password1) htpasswdPath := test.MakeHtpasswdFileFromString(testString1) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ @@ -9885,6 +10208,7 @@ func TestSearchRoutes(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() img := CreateRandomImage() @@ -9903,6 +10227,7 @@ func TestSearchRoutes(t *testing.T) { group1 := "testgroup" testString1 := test.GetCredString(user1, password1) htpasswdPath := test.MakeHtpasswdFileFromString(testString1) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ @@ -9953,6 +10278,7 @@ func TestSearchRoutes(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() img := CreateRandomImage() @@ -9970,8 +10296,11 @@ func TestSearchRoutes(t *testing.T) { password1 := "test4" group1 := "testgroup1" testString1 := test.GetCredString(user1, password1) + htpasswdPath := test.MakeHtpasswdFileFromString(testString1) + defer os.Remove(htpasswdPath) + conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ Path: htpasswdPath, @@ -10021,6 +10350,7 @@ func TestSearchRoutes(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() img := CreateRandomImage() @@ -10039,6 +10369,7 @@ func TestSearchRoutes(t *testing.T) { group1 := "testgroup2" testString1 := test.GetCredString(user1, password1) htpasswdPath := test.MakeHtpasswdFileFromString(testString1) + defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ @@ -10075,6 +10406,7 @@ func TestSearchRoutes(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() img := CreateRandomImage() @@ -10094,6 +10426,7 @@ func TestSearchRoutes(t *testing.T) { group1, seedGroup1 := test.GenerateRandomString() user1, seedUser1 := test.GenerateRandomString() password1, seedPass1 := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(user1, password1)) defer os.Remove(htpasswdPath) @@ -10140,6 +10473,7 @@ func TestSearchRoutes(t *testing.T) { cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() img := CreateRandomImage() @@ -10173,13 +10507,16 @@ func TestDistSpecExtensions(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // clean up ctlr := makeController(conf, t.TempDir()) cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() var extensionList distext.ExtensionList @@ -10221,13 +10558,16 @@ func TestDistSpecExtensions(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // clean up ctlr := makeController(conf, t.TempDir()) cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() var extensionList distext.ExtensionList @@ -10235,7 +10575,9 @@ func TestDistSpecExtensions(t *testing.T) { resp, err := resty.R().Get(baseURL + constants.RoutePrefix + constants.ExtOciDiscoverPrefix) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) + So(resp.StatusCode(), ShouldEqual, 200) + err = json.Unmarshal(resp.Body(), &extensionList) So(err, ShouldBeNil) t.Log(extensionList.Extensions) @@ -10263,13 +10605,16 @@ func TestDistSpecExtensions(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // clean up ctlr := makeController(conf, t.TempDir()) cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() var extensionList distext.ExtensionList @@ -10294,16 +10639,20 @@ func TestDistSpecExtensions(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // clean up ctlr := makeController(conf, t.TempDir()) cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() var extensionList distext.ExtensionList + resp, err := resty.R().Get(baseURL + constants.RoutePrefix + constants.ExtOciDiscoverPrefix) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -10327,6 +10676,7 @@ func TestHTTPOptionsResponse(t *testing.T) { firstDir := t.TempDir() secondDir := t.TempDir() + defer os.RemoveAll(firstDir) defer os.RemoveAll(secondDir) @@ -10452,12 +10802,12 @@ func getAllBlobs(imagePath string) []string { p := path.Join(imagePath, "blobs", digest.Algorithm().String(), digest.Encoded()) buf, err = os.ReadFile(p) - if err != nil { panic(err) } var manifest ispec.Manifest + if err := json.Unmarshal(buf, &manifest); err != nil { panic(err) } @@ -10550,7 +10900,7 @@ func RunAuthorizationWithMultiplePoliciesTests(t *testing.T, userClient *resty.C // uploading blob should get 201 resp, err = userClient.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). @@ -10695,7 +11045,9 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL, user str So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var apiErr apiErr.Error + err = json.Unmarshal(resp.Body(), &apiErr) So(err, ShouldBeNil) @@ -10719,7 +11071,7 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL, user str // uploading blob should get 201 resp, err = client.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). @@ -10800,7 +11152,7 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL, user str // uploading blob should get 201 resp, err = client.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). @@ -10888,6 +11240,7 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL, user str So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + err = json.Unmarshal(resp.Body(), &apiErr) So(err, ShouldBeNil) @@ -10897,6 +11250,7 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL, user str err = json.Unmarshal(resp.Body(), &catalog) So(err, ShouldBeNil) + So(len(catalog.Repositories), ShouldEqual, 2) So(catalog.Repositories, ShouldContain, "zot-test") So(catalog.Repositories, ShouldContain, AuthorizationNamespace) @@ -10908,6 +11262,7 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL, user str So(resp.StatusCode(), ShouldEqual, http.StatusOK) manifestBlob := resp.Body() + var manifest ispec.Manifest err = json.Unmarshal(manifestBlob, &manifest) @@ -10945,7 +11300,7 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL, user str // uploading blob should get 201 resp, err = client.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -10965,7 +11320,7 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL, user str // uploading blob should get 201 resp, err = client.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(updateBlob))). + SetHeader("Content-Length", strconv.Itoa(len(updateBlob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", string(godigest.FromBytes(updateBlob))). SetBody(updateBlob). @@ -11111,7 +11466,7 @@ func RunAuthorizationTests(t *testing.T, client *resty.Client, baseURL, user str // uploading blob should get 201 resp, err = client.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). diff --git a/pkg/api/cookiestore.go b/pkg/api/cookiestore.go index b8d40d7e..6a58e234 100644 --- a/pkg/api/cookiestore.go +++ b/pkg/api/cookiestore.go @@ -147,7 +147,7 @@ func (gen *SessionCleanup) Next() (scheduler.Task, error) { if len(sessions) == 0 { gen.done = true - return nil, nil + return nil, nil //nolint:nilnil } return &CleanTask{sessions: sessions}, nil diff --git a/pkg/api/ldap.go b/pkg/api/ldap.go index 94682feb..9101093b 100644 --- a/pkg/api/ldap.go +++ b/pkg/api/ldap.go @@ -66,7 +66,6 @@ func (lc *LDAPClient) Connect() error { } err = l.StartTLS(config) - if err != nil { lc.Log.Error().Err(err).Str("address", address).Msg("failed to establish a TLS connection") @@ -81,8 +80,8 @@ func (lc *LDAPClient) Connect() error { } if lc.ClientCertificates != nil && len(lc.ClientCertificates) > 0 { config.Certificates = lc.ClientCertificates - // config.BuildNameToCertificate() } + l, err = ldap.DialTLS("tcp", address, config) //nolint:staticcheck if err != nil { lc.Log.Error().Err(err).Str("address", address).Msg("failed to establish a TLS connection") @@ -226,6 +225,7 @@ func (lc *LDAPClient) Authenticate(username, password string) (bool, map[string] userAttributes := search.Entries[0].Attributes[0] userGroups = userAttributes.Values } + user := map[string]string{} for _, attr := range lc.Attributes { diff --git a/pkg/api/routes.go b/pkg/api/routes.go index 1314f5f5..e4da26fe 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -38,7 +38,7 @@ import ( apiErr "zotregistry.dev/zot/pkg/api/errors" zcommon "zotregistry.dev/zot/pkg/common" gqlPlayground "zotregistry.dev/zot/pkg/debug/gqlplayground" - pprof "zotregistry.dev/zot/pkg/debug/pprof" + "zotregistry.dev/zot/pkg/debug/pprof" debug "zotregistry.dev/zot/pkg/debug/swagger" ext "zotregistry.dev/zot/pkg/extensions" syncConstants "zotregistry.dev/zot/pkg/extensions/sync/constants" @@ -76,10 +76,10 @@ func (rh *RouteHandler) SetupRoutes() { // callback path for openID for provider, relyingParty := range rh.c.RelyingParties { if config.IsOauth2Supported(provider) { - rh.c.Router.HandleFunc(constants.CallbackBasePath+fmt.Sprintf("/%s", provider), + rh.c.Router.HandleFunc(constants.CallbackBasePath+"/"+provider, rp.CodeExchangeHandler(rh.GithubCodeExchangeCallback(), relyingParty)) } else if config.IsOpenIDSupported(provider) { - rh.c.Router.HandleFunc(constants.CallbackBasePath+fmt.Sprintf("/%s", provider), + rh.c.Router.HandleFunc(constants.CallbackBasePath+"/"+provider, rp.CodeExchangeHandler(rp.UserinfoCallback(rh.OpenIDCodeExchangeCallback()), relyingParty)) } } @@ -265,9 +265,9 @@ func (rh *RouteHandler) CheckVersionSupport(response http.ResponseWriter, reques // don't send auth headers if request is coming from UI if request.Header.Get(constants.SessionClientHeaderName) != constants.SessionClientHeaderValue { if rh.c.Config.HTTP.Auth.Bearer != nil { - response.Header().Set("WWW-Authenticate", fmt.Sprintf("bearer realm=%s", rh.c.Config.HTTP.Auth.Bearer.Realm)) + response.Header().Set("WWW-Authenticate", "bearer realm="+rh.c.Config.HTTP.Auth.Bearer.Realm) } else { - response.Header().Set("WWW-Authenticate", fmt.Sprintf("basic realm=%s", rh.c.Config.HTTP.Realm)) + response.Header().Set("WWW-Authenticate", "basic realm="+rh.c.Config.HTTP.Realm) } } } @@ -458,6 +458,7 @@ func (rh *RouteHandler) CheckManifest(response http.ResponseWriter, request *htt zcommon.WriteJSON(response, http.StatusNotFound, apiErr.NewErrorList(e)) } else { rh.c.Log.Error().Err(err).Msg("unexpected error") + e := apiErr.NewError(apiErr.MANIFEST_INVALID).AddDetail(details) zcommon.WriteJSON(response, http.StatusInternalServerError, apiErr.NewErrorList(e)) } @@ -466,7 +467,7 @@ func (rh *RouteHandler) CheckManifest(response http.ResponseWriter, request *htt } response.Header().Set(constants.DistContentDigestKey, digest.String()) - response.Header().Set("Content-Length", fmt.Sprintf("%d", len(content))) + response.Header().Set("Content-Length", strconv.Itoa(len(content))) response.Header().Set("Content-Type", mediaType) response.WriteHeader(http.StatusOK) } @@ -548,7 +549,7 @@ func (rh *RouteHandler) GetManifest(response http.ResponseWriter, request *http. } response.Header().Set(constants.DistContentDigestKey, digest.String()) - response.Header().Set("Content-Length", fmt.Sprintf("%d", len(content))) + response.Header().Set("Content-Length", strconv.Itoa(len(content))) response.Header().Set("Content-Type", mediaType) zcommon.WriteData(response, http.StatusOK, mediaType, content) } @@ -607,8 +608,8 @@ func (rh *RouteHandler) GetReferrers(response http.ResponseWriter, request *http } digestStr, ok := vars["digest"] - digest, err := godigest.Parse(digestStr) + digest, err := godigest.Parse(digestStr) if !ok || digestStr == "" || err != nil { response.WriteHeader(http.StatusBadRequest) @@ -647,7 +648,7 @@ func (rh *RouteHandler) GetReferrers(response http.ResponseWriter, request *http if len(artifactTypes) > 0 { // currently, the only filter supported and on this end-point - response.Header().Set("OCI-Filters-Applied", "artifactType") + response.Header().Set("OCI-Filters-Applied", "artifactType") //nolint:canonicalheader } zcommon.WriteData(response, http.StatusOK, ispec.MediaTypeImageIndex, out) @@ -991,7 +992,7 @@ func (rh *RouteHandler) CheckBlob(response http.ResponseWriter, request *http.Re return } - response.Header().Set("Content-Length", fmt.Sprintf("%d", blen)) + response.Header().Set("Content-Length", strconv.FormatInt(blen, 10)) response.Header().Set("Accept-Ranges", "bytes") response.Header().Set(constants.DistContentDigestKey, digest.String()) response.WriteHeader(http.StatusOK) @@ -1018,6 +1019,7 @@ func parseRangeHeader(contentRange string) (int64, int64, error) { } var from int64 + to := int64(-1) rangeFrom := paramsMap["rangeFrom"] @@ -1135,9 +1137,10 @@ func (rh *RouteHandler) GetBlob(response http.ResponseWriter, request *http.Requ return } + defer repo.Close() - response.Header().Set("Content-Length", fmt.Sprintf("%d", blen)) + response.Header().Set("Content-Length", strconv.FormatInt(blen, 10)) status := http.StatusOK @@ -1173,8 +1176,8 @@ func (rh *RouteHandler) DeleteBlob(response http.ResponseWriter, request *http.R } digestStr, ok := vars["digest"] - digest, err := godigest.Parse(digestStr) + digest, err := godigest.Parse(digestStr) if !ok || digestStr == "" || err != nil { response.WriteHeader(http.StatusNotFound) @@ -1330,6 +1333,7 @@ func (rh *RouteHandler) CreateBlobUpload(response http.ResponseWriter, request * contentLength, err := strconv.ParseInt(request.Header.Get("Content-Length"), 10, 64) if err != nil || contentLength <= 0 { rh.c.Log.Warn().Str("actual", request.Header.Get("Content-Length")).Msg("invalid content length") + details := map[string]string{"digest": digest.String()} if err != nil { @@ -1337,6 +1341,7 @@ func (rh *RouteHandler) CreateBlobUpload(response http.ResponseWriter, request * } else { details["Content-Length"] = request.Header.Get("Content-Length") } + e := apiErr.NewError(apiErr.BLOB_UPLOAD_INVALID).AddDetail(details) zcommon.WriteJSON(response, http.StatusBadRequest, apiErr.NewErrorList(e)) @@ -1491,7 +1496,6 @@ func (rh *RouteHandler) PatchBlobUpload(response http.ResponseWriter, request *h clen, err = imgStore.PutBlobChunkStreamed(name, sessionID, request.Body) } else { // chunked blob upload - var contentLength int64 if contentLength, err = strconv.ParseInt(request.Header.Get("Content-Length"), 10, 64); err != nil { @@ -1533,6 +1537,7 @@ func (rh *RouteHandler) PatchBlobUpload(response http.ResponseWriter, request *h rh.c.Log.Error().Err(err).Str("blobUpload", sessionID).Str("repository", name). Msg("couldn't remove blobUpload in repo") } + response.WriteHeader(http.StatusInternalServerError) } @@ -1655,6 +1660,7 @@ func (rh *RouteHandler) UpdateBlobUpload(response http.ResponseWriter, request * rh.c.Log.Error().Err(err).Str("blobUpload", sessionID).Str("repository", name). Msg("failed to remove blobUpload in repo") } + response.WriteHeader(http.StatusInternalServerError) } diff --git a/pkg/api/routes_test.go b/pkg/api/routes_test.go index a4dd62c3..3de25215 100644 --- a/pkg/api/routes_test.go +++ b/pkg/api/routes_test.go @@ -47,12 +47,14 @@ func TestRoutes(t *testing.T) { username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) mockOIDCServer, err := mockoidc.Run() if err != nil { panic(err) } + defer func() { err := mockOIDCServer.Shutdown() if err != nil { @@ -305,6 +307,7 @@ func TestRoutes(t *testing.T) { ctlr.StoreController.DefaultStore = ism request, _ := http.NewRequestWithContext(context.Background(), http.MethodDelete, baseURL, nil) request = mux.SetURLVars(request, urlVars) + for k, v := range headers { request.Header.Add(k, v) } diff --git a/pkg/api/session.go b/pkg/api/session.go index b923066b..79ada785 100644 --- a/pkg/api/session.go +++ b/pkg/api/session.go @@ -90,25 +90,30 @@ func SessionLogger(ctlr *Controller) mux.MiddlewareFunc { method := request.Method headers := map[string][]string{} log := logger.Info() //nolint: zerologlint // false positive, the Msg call is below + for key, value := range request.Header { if key == "Authorization" { // anonymize from logs - s := strings.SplitN(value[0], " ", 2) //nolint:gomnd + s := strings.SplitN(value[0], " ", 2) //nolint:mnd if len(s) == 2 && strings.EqualFold(s[0], "basic") { b, err := base64.StdEncoding.DecodeString(s[1]) if err == nil { - pair := strings.SplitN(string(b), ":", 2) //nolint:gomnd - //nolint:gomnd + pair := strings.SplitN(string(b), ":", 2) //nolint:mnd + //nolint:mnd if len(pair) == 2 { log = log.Str("username", pair[0]) } } } + value = []string{"******"} } + headers[key] = value } + statusCode := stwr.status bodySize := stwr.length + if raw != "" { path = path + "?" + raw } @@ -151,12 +156,12 @@ func SessionAuditLogger(audit *log.Logger) mux.MiddlewareFunc { for key, value := range request.Header { if key == "Authorization" { // anonymize from logs - s := strings.SplitN(value[0], " ", 2) //nolint:gomnd + s := strings.SplitN(value[0], " ", 2) //nolint:mnd if len(s) == 2 && strings.EqualFold(s[0], "basic") { b, err := base64.StdEncoding.DecodeString(s[1]) if err == nil { - pair := strings.SplitN(string(b), ":", 2) //nolint:gomnd - if len(pair) == 2 { //nolint:gomnd + pair := strings.SplitN(string(b), ":", 2) //nolint:mnd + if len(pair) == 2 { //nolint:mnd username = pair[0] } } @@ -165,6 +170,7 @@ func SessionAuditLogger(audit *log.Logger) mux.MiddlewareFunc { } statusCode := statusWr.status + if raw != "" { path = path + "?" + raw } diff --git a/pkg/cli/client/client.go b/pkg/cli/client/client.go index 912f4198..e6017cfa 100644 --- a/pkg/cli/client/client.go +++ b/pkg/cli/client/client.go @@ -450,7 +450,7 @@ func fetchManifestStruct(ctx context.Context, repo, manifestReference string, se layers = append( layers, common.LayerSummary{ - Size: fmt.Sprintf("%v", entry.Size), + Size: strconv.FormatInt(entry.Size, 10), Digest: entry.Digest.String(), }, ) diff --git a/pkg/cli/client/client_test.go b/pkg/cli/client/client_test.go index 00b5c5a0..89da85c6 100644 --- a/pkg/cli/client/client_test.go +++ b/pkg/cli/client/client_test.go @@ -47,11 +47,14 @@ func TestTLSWithAuth(t *testing.T) { caCertPool.AppendCertsFromPEM(caCert) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = SecurePort1 username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) defer os.Remove(htpasswdPath) @@ -75,6 +78,7 @@ func TestTLSWithAuth(t *testing.T) { ctlr := api.NewController(conf) ctlr.Log.Info().Int64("seedUser", seedUser).Int64("seedPass", seedPass).Msg("random seed for username & password") ctlr.Config.Storage.RootDirectory = t.TempDir() + cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) defer cm.StopServer() @@ -101,10 +105,12 @@ func TestTLSWithAuth(t *testing.T) { So(imageBuff.String(), ShouldContainSubstring, "scheme not provided") args = []string{"list", "--config", "imagetest"} + configPath = makeConfigFile( fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`, BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix)) defer os.Remove(configPath) + imageCmd = client.NewImageCommand(client.NewSearchService()) imageBuff = bytes.NewBufferString("") imageCmd.SetOut(imageBuff) @@ -116,10 +122,12 @@ func TestTLSWithAuth(t *testing.T) { user := fmt.Sprintf("%s:%s", username, password) args = []string{"-u", user, "--config", "imagetest"} + configPath = makeConfigFile( fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`, BaseSecureURL1, constants.RoutePrefix, constants.ExtCatalogPrefix)) defer os.Remove(configPath) + imageCmd = client.NewImageCommand(client.NewSearchService()) imageBuff = bytes.NewBufferString("") imageCmd.SetOut(imageBuff) @@ -139,7 +147,9 @@ func TestTLSWithoutAuth(t *testing.T) { caCertPool.AppendCertsFromPEM(caCert) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = SecurePort1 conf.HTTP.TLS = &config.TLSConfig{ @@ -155,6 +165,7 @@ func TestTLSWithoutAuth(t *testing.T) { ctlr := api.NewController(conf) ctlr.Config.Storage.RootDirectory = t.TempDir() + cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) defer cm.StopServer() @@ -189,11 +200,14 @@ func TestTLSBadCerts(t *testing.T) { Convey("Make a new controller", t, func() { caCert, err := os.ReadFile(CACert) So(err, ShouldBeNil) + caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = SecurePort3 conf.HTTP.TLS = &config.TLSConfig{ @@ -204,6 +218,7 @@ func TestTLSBadCerts(t *testing.T) { ctlr := api.NewController(conf) ctlr.Config.Storage.RootDirectory = t.TempDir() + cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) defer cm.StopServer() diff --git a/pkg/cli/client/config_cmd.go b/pkg/cli/client/config_cmd.go index 12b41696..a53f61d1 100644 --- a/pkg/cli/client/config_cmd.go +++ b/pkg/cli/client/config_cmd.go @@ -223,7 +223,7 @@ func getConfigNames(configPath string) (string, error) { var builder strings.Builder - writer := tabwriter.NewWriter(&builder, 0, 8, 1, '\t', tabwriter.AlignRight) //nolint:gomnd + writer := tabwriter.NewWriter(&builder, 0, 8, 1, '\t', tabwriter.AlignRight) //nolint:mnd for _, val := range configs { configMap, ok := val.(map[string]interface{}) diff --git a/pkg/cli/client/config_cmd_test.go b/pkg/cli/client/config_cmd_test.go index 8051ac4b..f4825c0a 100644 --- a/pkg/cli/client/config_cmd_test.go +++ b/pkg/cli/client/config_cmd_test.go @@ -20,26 +20,33 @@ import ( func TestConfigCmdBasics(t *testing.T) { Convey("Test config help", t, func() { args := []string{"--help"} + configPath := makeConfigFile("showspinner = false") defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) err := cmd.Execute() - So(buff.String(), ShouldContainSubstring, "Usage") + So(err, ShouldBeNil) + So(buff.String(), ShouldContainSubstring, "Usage") + Convey("with the shorthand", func() { args[0] = "-h" + configPath := makeConfigFile("showspinner = false") defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) err := cmd.Execute() + So(buff.String(), ShouldContainSubstring, "Usage") So(err, ShouldBeNil) }) @@ -47,14 +54,17 @@ func TestConfigCmdBasics(t *testing.T) { Convey("Test config no args", t, func() { args := []string{} + configPath := makeConfigFile("showspinner = false") defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) err := cmd.Execute() + So(buff.String(), ShouldContainSubstring, "Usage") So(err, ShouldNotBeNil) }) @@ -63,8 +73,10 @@ func TestConfigCmdBasics(t *testing.T) { func TestConfigCmdMain(t *testing.T) { Convey("Test add config", t, func() { args := []string{"add", "configtest1", "https://test-url.com"} + file := makeConfigFile("") defer os.Remove(file) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -83,6 +95,7 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test error on home directory", t, func() { args := []string{"add", "configtest1", "https://test-url.com"} + file := makeConfigFile("") defer os.Remove(file) @@ -103,6 +116,7 @@ func TestConfigCmdMain(t *testing.T) { if err != nil { panic(err) } + err = os.Setenv("HOME", home) if err != nil { log.Fatal(err) @@ -111,6 +125,7 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test error on home directory at new add config", t, func() { args := []string{"add", "configtest1", "https://test-url.com"} + file := makeConfigFile("") defer os.Remove(file) @@ -131,6 +146,7 @@ func TestConfigCmdMain(t *testing.T) { if err != nil { panic(err) } + err = os.Setenv("HOME", home) if err != nil { log.Fatal(err) @@ -139,8 +155,10 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test add config with invalid format", t, func() { args := []string{"--list"} + configPath := makeConfigFile(`{"configs":{"_name":"configtest","url":"https://test-url.com","showspinner":false}}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -152,8 +170,10 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test add config with invalid URL", t, func() { args := []string{"add", "configtest1", "test..com"} + file := makeConfigFile("") defer os.Remove(file) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -166,8 +186,10 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test remove config entry successfully", t, func() { args := []string{"remove", "configtest"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -184,8 +206,10 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test remove missing config entry", t, func() { args := []string{"remove", "configtest"} + configPath := makeConfigFile(`{"configs":[]`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -198,8 +222,10 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test remove bad config file content", t, func() { args := []string{"remove", "configtest"} + configPath := makeConfigFile(`{"asdf":[]`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -212,8 +238,10 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test remove bad config file entry", t, func() { args := []string{"remove", "configtest"} + configPath := makeConfigFile(`{"configs":[asdad]`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -227,12 +255,15 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test remove config bad permissions", t, func() { args := []string{"remove", "configtest"} configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) + defer func() { _ = os.Chmod(configPath, 0o600) os.Remove(configPath) }() + err := os.Chmod(configPath, 0o400) // Read-only, so we fail only on updating the file, not reading So(err, ShouldBeNil) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -245,122 +276,154 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test fetch all config", t, func() { args := []string{"--list"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) err := cmd.Execute() + So(buff.String(), ShouldContainSubstring, "https://test-url.com") So(err, ShouldBeNil) Convey("with the shorthand", func() { args := []string{"-l"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() - So(buff.String(), ShouldContainSubstring, "https://test-url.com") So(err, ShouldBeNil) + + So(buff.String(), ShouldContainSubstring, "https://test-url.com") }) Convey("From empty file", func() { args := []string{"-l"} + configPath := makeConfigFile(``) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() So(err, ShouldBeNil) + So(strings.TrimSpace(buff.String()), ShouldEqual, "") }) }) Convey("Test fetch a config", t, func() { args := []string{"configtest", "--list"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() + So(err, ShouldBeNil) + So(buff.String(), ShouldContainSubstring, "url = https://test-url.com") So(buff.String(), ShouldContainSubstring, "showspinner = false") - So(err, ShouldBeNil) Convey("with the shorthand", func() { args := []string{"configtest", "-l"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() + So(err, ShouldBeNil) + So(buff.String(), ShouldContainSubstring, "url = https://test-url.com") So(buff.String(), ShouldContainSubstring, "showspinner = false") - So(err, ShouldBeNil) }) Convey("From empty file", func() { args := []string{"configtest", "-l"} + configPath := makeConfigFile(``) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() So(err, ShouldBeNil) + So(strings.TrimSpace(buff.String()), ShouldEqual, "") }) }) Convey("Test fetch a config val", t, func() { args := []string{"configtest", "url"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() - So(buff.String(), ShouldEqual, "https://test-url.com\n") So(err, ShouldBeNil) + So(buff.String(), ShouldEqual, "https://test-url.com\n") Convey("From empty file", func() { args := []string{"configtest", "url"} + configPath := makeConfigFile(``) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() So(err, ShouldNotBeNil) + So(buff.String(), ShouldContainSubstring, "does not exist") }) }) Convey("Test add a config val", t, func() { args := []string{"configtest", "showspinner", "false"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com"}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -380,23 +443,29 @@ func TestConfigCmdMain(t *testing.T) { Convey("To an empty file", func() { args := []string{"configtest", "showspinner", "false"} + configPath := makeConfigFile(``) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() So(err, ShouldNotBeNil) + So(buff.String(), ShouldContainSubstring, "does not exist") }) }) Convey("Test overwrite a config", t, func() { args := []string{"configtest", "url", "https://new-url.com"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -418,8 +487,10 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test reset a config val", t, func() { args := []string{"configtest", "showspinner", "--reset"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -440,29 +511,37 @@ func TestConfigCmdMain(t *testing.T) { Convey("Test reset a url", t, func() { args := []string{"configtest", "url", "--reset"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() So(err, ShouldNotBeNil) + So(buff.String(), ShouldContainSubstring, "cannot reset") }) Convey("Test add a config with an existing saved name", t, func() { args := []string{"add", "configtest", "https://test-url.com/new"} + configPath := makeConfigFile(`{"configs":[{"_name":"configtest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := client.NewConfigCommand() buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() So(err, ShouldNotBeNil) + So(buff.String(), ShouldContainSubstring, "cli config name already added") }) } diff --git a/pkg/cli/client/cve_cmd_internal_test.go b/pkg/cli/client/cve_cmd_internal_test.go index 327f776c..6f365941 100644 --- a/pkg/cli/client/cve_cmd_internal_test.go +++ b/pkg/cli/client/cve_cmd_internal_test.go @@ -47,36 +47,44 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE help", t, func() { args := []string{"--help"} + configPath := makeConfigFile("") defer os.Remove(configPath) + cmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) err := cmd.Execute() + So(buff.String(), ShouldContainSubstring, "Usage") So(err, ShouldBeNil) }) Convey("Test CVE help - with the shorthand", t, func() { args := []string{"-h"} + configPath := makeConfigFile("") defer os.Remove(configPath) + cmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) err := cmd.Execute() + So(buff.String(), ShouldContainSubstring, "Usage") So(err, ShouldBeNil) }) Convey("Test CVE no url", t, func() { args := []string{"affected", "CVE-cveIdRandom", "--config", "cvetest"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -89,8 +97,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE invalid url", t, func() { args := []string{"list", "dummyImageName:tag", "--url", "invalidUrl"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewCVECommand(new(searchService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -104,8 +114,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE invalid url port", t, func() { args := []string{"list", "dummyImageName:tag", "--url", "http://localhost:99999"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewCVECommand(new(searchService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -118,8 +130,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE unreachable", t, func() { args := []string{"list", "dummyImageName:tag", "--url", "http://localhost:9999"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewCVECommand(new(searchService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -131,8 +145,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE url from config", t, func() { args := []string{"list", "dummyImageName:tag", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, baseURL)) defer os.Remove(configPath) + cmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -161,8 +177,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test debug flag", t, func() { args := []string{"list", "dummyImageName:tag", "--debug", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, baseURL)) defer os.Remove(configPath) + cmd := NewCVECommand(new(searchService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -177,8 +195,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE by name and CVE ID - long option", t, func() { args := []string{"affected", "CVE-CVEID", "--repo", "dummyImageName", "--url", baseURL} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -195,8 +215,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE by name and CVE ID - using shorthand", t, func() { args := []string{"affected", "CVE-CVEID", "--repo", "dummyImageName", "--url", baseURL} buff := bytes.NewBufferString("") + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(new(mockService)) cveCmd.SetOut(buff) cveCmd.SetErr(buff) @@ -211,8 +233,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE by image name - in text format", t, func() { args := []string{"list", "dummyImageName:tag", "--url", baseURL} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -241,8 +265,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE by image name - in text format - in verbose mode", t, func() { args := []string{"list", "dummyImageName:tag", "--url", baseURL, "--verbose"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -278,8 +304,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE by image name - in json format", t, func() { args := []string{"list", "dummyImageName:tag", "--url", baseURL, "-f", "json"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -298,8 +326,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test CVE by image name - in yaml format", t, func() { args := []string{"list", "dummyImageName:tag", "--url", baseURL, "-f", "yaml"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -316,24 +346,30 @@ func TestSearchCVECmd(t *testing.T) { }) Convey("Test CVE by image name - invalid format", t, func() { args := []string{"list", "dummyImageName:tag", "--url", baseURL, "-f", "random"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) err := cveCmd.Execute() + space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") + So(err, ShouldNotBeNil) So(strings.TrimSpace(str), ShouldContainSubstring, zerr.ErrInvalidOutputFormat.Error()) }) Convey("Test images by CVE ID - positive", t, func() { args := []string{"affected", "CVE-CVEID", "--repo", "anImage", "--url", baseURL} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -342,14 +378,17 @@ func TestSearchCVECmd(t *testing.T) { err := cveCmd.Execute() space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") + So(strings.TrimSpace(str), ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE anImage tag os/arch 6e2f80bf false 123kB") //nolint:lll So(err, ShouldBeNil) }) Convey("Test images by CVE ID - positive with retries", t, func() { args := []string{"affected", "CVE-CVEID", "--repo", "anImage", "--url", baseURL} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + mockService := mockServiceForRetry{succeedOn: 2} // CVE info will be provided in 2nd attempt cveCmd := NewCVECommand(&mockService) buff := bytes.NewBufferString("") @@ -369,8 +408,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test images by CVE ID - failed after retries", t, func() { args := []string{"affected", "CVE-CVEID", "--url", baseURL} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + mockService := mockServiceForRetry{succeedOn: -1} // CVE info will be unavailable on all retries cveCmd := NewCVECommand(&mockService) buff := bytes.NewBufferString("") @@ -390,8 +431,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test images by CVE ID - invalid CVE ID", t, func() { args := []string{"affected", "CVE-invalidCVEID", "--config", "cvetest"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -403,8 +446,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test images by CVE ID - invalid url", t, func() { args := []string{"affected", "CVE-CVEID", "--url", "invalidURL"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -418,8 +463,10 @@ func TestSearchCVECmd(t *testing.T) { Convey("Test fixed tags by and image name CVE ID - positive", t, func() { args := []string{"fixed", "fixedImage", "CVE-CVEID", "--url", baseURL} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(new(mockService)) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -428,14 +475,17 @@ func TestSearchCVECmd(t *testing.T) { err := cveCmd.Execute() space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") + So(err, ShouldBeNil) So(strings.TrimSpace(str), ShouldEqual, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE fixedImage tag os/arch 6e2f80bf false 123kB") //nolint:lll }) Convey("Test fixed tags by and image name CVE ID - invalid image name", t, func() { args := []string{"affected", "CVE-CVEID", "--image", "invalidImageName", "--config", "cvetest"} + configPath := makeConfigFile(`{"configs":[{"_name":"cvetest","showspinner":false}]}`) defer os.Remove(configPath) + cveCmd := NewCVECommand(NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -487,10 +537,12 @@ func TestCVECommandGQL(t *testing.T) { Convey("cveid db download wait", func() { count := 0 + args := []string{"affected", "CVE-12345", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, baseURL)) - args := []string{"affected", "CVE-12345", "--config", "cvetest"} defer os.Remove(configPath) + cmd := NewCVECommand(mockService{ getTagsForCVEGQLFn: func(ctx context.Context, config SearchConfig, username, password, imageName, cveID string) (*zcommon.ImagesForCve, error, @@ -534,10 +586,12 @@ func TestCVECommandGQL(t *testing.T) { Convey("fixed db download wait", func() { count := 0 + args := []string{"fixed", "repo", "CVE-2222", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, baseURL)) - args := []string{"fixed", "repo", "CVE-2222", "--config", "cvetest"} defer os.Remove(configPath) + cmd := NewCVECommand(mockService{ getFixedTagsForCVEGQLFn: func(ctx context.Context, config SearchConfig, username, password, imageName, cveID string) (*zcommon.ImageListWithCVEFixedResponse, error, @@ -571,8 +625,10 @@ func TestCVECommandGQL(t *testing.T) { cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() So(err, ShouldBeNil) + space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") actual := strings.TrimSpace(str) @@ -582,10 +638,12 @@ func TestCVECommandGQL(t *testing.T) { Convey("image db download wait", func() { count := 0 + args := []string{"list", "repo:vuln", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, baseURL)) - args := []string{"list", "repo:vuln", "--config", "cvetest"} defer os.Remove(configPath) + cmd := NewCVECommand(mockService{ getCveByImageGQLFn: func(ctx context.Context, config SearchConfig, username, password, imageName, searchedCVE string) (*cveResult, error, diff --git a/pkg/cli/client/cve_cmd_test.go b/pkg/cli/client/cve_cmd_test.go index e06a6c91..8d05d1cf 100644 --- a/pkg/cli/client/cve_cmd_test.go +++ b/pkg/cli/client/cve_cmd_test.go @@ -95,8 +95,10 @@ func TestNegativeServerResponse(t *testing.T) { Convey("Status Code Not Found", func() { args := []string{"list", "zot-cve-test:0.0.1", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -186,8 +188,10 @@ func TestNegativeServerResponse(t *testing.T) { } args := []string{"fixed", "zot-cve-test", "CVE-2019-9923", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -383,15 +387,19 @@ func TestCVEDiffList(t *testing.T) { Convey("Test CVE by image name - GQL - positive", t, func() { args := []string{"diff", "repo:image", "repo:base-image", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) err = cveCmd.Execute() + fmt.Println(buff.String()) + space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) @@ -401,9 +409,9 @@ func TestCVEDiffList(t *testing.T) { }) Convey("Errors", t, func() { - // args := []string{"diff", "repo:image", "repo:base-image", "--config", "cvetest"} configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) Convey("Set wrong number of params", func() { @@ -538,8 +546,10 @@ func TestServerCVEResponse(t *testing.T) { Convey("Test CVE by image name - GQL - positive", t, func() { args := []string{"list", "zot-cve-test:0.0.1", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -549,6 +559,7 @@ func TestServerCVEResponse(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) + So(err, ShouldBeNil) So(str, ShouldContainSubstring, "ID SEVERITY TITLE") So(str, ShouldContainSubstring, "CVE") @@ -556,8 +567,10 @@ func TestServerCVEResponse(t *testing.T) { Convey("Test CVE by image name - GQL - search CVE by title in results", t, func() { args := []string{"list", "zot-cve-test:0.0.1", "--cve-id", "CVE-C1", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -567,6 +580,7 @@ func TestServerCVEResponse(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) + So(err, ShouldBeNil) So(str, ShouldContainSubstring, "ID SEVERITY TITLE") So(str, ShouldContainSubstring, "CVE-C1") @@ -575,18 +589,24 @@ func TestServerCVEResponse(t *testing.T) { Convey("Test CVE by image name - GQL - search CVE by id in results", t, func() { args := []string{"list", "zot-cve-test:0.0.1", "--cve-id", "CVE-2", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) + err = cveCmd.Execute() + So(err, ShouldBeNil) + space := regexp.MustCompile(`\s+`) + str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) - So(err, ShouldBeNil) + So(str, ShouldContainSubstring, "ID SEVERITY TITLE") So(str, ShouldContainSubstring, "CVE-2") So(str, ShouldNotContainSubstring, "CVE-1") @@ -594,8 +614,10 @@ func TestServerCVEResponse(t *testing.T) { Convey("Test CVE by image name - GQL - search nonexistent CVE", t, func() { args := []string{"list", "zot-cve-test:0.0.1", "--cve-id", "CVE-100", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -605,14 +627,17 @@ func TestServerCVEResponse(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) + So(err, ShouldBeNil) So(str, ShouldContainSubstring, "No CVEs found for image") }) Convey("Test CVE by image name - GQL - invalid image", t, func() { args := []string{"list", "invalid:0.0.1", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -624,8 +649,10 @@ func TestServerCVEResponse(t *testing.T) { Convey("Test CVE by image name - GQL - invalid image name and tag", t, func() { args := []string{"list", "invalid:", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -637,56 +664,71 @@ func TestServerCVEResponse(t *testing.T) { Convey("Test CVE by image name - GQL - invalid cli output format", t, func() { args := []string{"list", "zot-cve-test:0.0.1", "-f", "random", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) err = cveCmd.Execute() + So(err, ShouldNotBeNil) So(buff.String(), ShouldContainSubstring, "invalid cli output format") }) Convey("Test images by CVE ID - GQL - positive", t, func() { args := []string{"affected", "CVE-2019-9923", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) + err := cveCmd.Execute() + So(err, ShouldBeNil) + space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) - So(err, ShouldBeNil) + So(str, ShouldEqual, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 linux/amd64 db573b01 false 854B") }) Convey("Test images by CVE ID - GQL - invalid CVE ID", t, func() { args := []string{"affected", "CVE-invalid", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) + err := cveCmd.Execute() + So(err, ShouldBeNil) + space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) - So(err, ShouldBeNil) + So(str, ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test images by CVE ID - GQL - invalid cli output format", t, func() { args := []string{"affected", "CVE-2019-9923", "-f", "random", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -699,25 +741,32 @@ func TestServerCVEResponse(t *testing.T) { Convey("Test fixed tags by image name and CVE ID - GQL - positive", t, func() { args := []string{"fixed", "zot-cve-test", "CVE-2019-9923", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) + err := cveCmd.Execute() + So(err, ShouldBeNil) + space := regexp.MustCompile(`\s+`) + str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) - So(err, ShouldBeNil) So(str, ShouldEqual, "") }) Convey("Test fixed tags by image name and CVE ID - GQL - random cve", t, func() { args := []string{"fixed", "zot-cve-test", "random", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) @@ -727,81 +776,104 @@ func TestServerCVEResponse(t *testing.T) { space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) + So(err, ShouldBeNil) So(strings.TrimSpace(str), ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test fixed tags by image name and CVE ID - GQL - random image", t, func() { args := []string{"fixed", "zot-cv-test", "CVE-2019-20807", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) + err := cveCmd.Execute() + So(err, ShouldNotBeNil) + space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) - So(err, ShouldNotBeNil) + So(strings.TrimSpace(str), ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test fixed tags by image name and CVE ID - GQL - invalid image", t, func() { args := []string{"fixed", "zot-cv-test:tag", "CVE-2019-20807", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) + err := cveCmd.Execute() + So(err, ShouldNotBeNil) + space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") str = strings.TrimSpace(str) - So(err, ShouldNotBeNil) + So(strings.TrimSpace(str), ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") }) Convey("Test CVE by name and CVE ID - GQL - positive", t, func() { args := []string{"affected", "CVE-2019-9923", "--repo", "zot-cve-test", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) + err := cveCmd.Execute() - space := regexp.MustCompile(`\s+`) - str := space.ReplaceAllString(buff.String(), " ") So(err, ShouldBeNil) + + space := regexp.MustCompile(`\s+`) + + str := space.ReplaceAllString(buff.String(), " ") So(strings.TrimSpace(str), ShouldEqual, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE zot-cve-test 0.0.1 linux/amd64 db573b01 false 854B") }) Convey("Test CVE by name and CVE ID - GQL - invalid name and CVE ID", t, func() { args := []string{"affected", "CVE-20807", "--repo", "test", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) cveCmd.SetErr(buff) cveCmd.SetArgs(args) + err := cveCmd.Execute() - space := regexp.MustCompile(`\s+`) - str := space.ReplaceAllString(buff.String(), " ") So(err, ShouldBeNil) + + space := regexp.MustCompile(`\s+`) + + str := space.ReplaceAllString(buff.String(), " ") So(strings.TrimSpace(str), ShouldNotContainSubstring, "REPOSITORY TAG OS/ARCH SIGNED SIZE") }) Convey("Test CVE by name and CVE ID - GQL - invalid cli output format", t, func() { args := []string{"affected", "CVE-2019-9923", "--repo", "zot-cve-test", "-f", "random", "--config", "cvetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"cvetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cveCmd := client.NewCVECommand(client.NewSearchService()) buff := bytes.NewBufferString("") cveCmd.SetOut(buff) diff --git a/pkg/cli/client/elevated_test.go b/pkg/cli/client/elevated_test.go index f40fb8f3..e9ef3395 100644 --- a/pkg/cli/client/elevated_test.go +++ b/pkg/cli/client/elevated_test.go @@ -26,6 +26,7 @@ import ( func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { Convey("Privileged certs - Make a new controller", t, func() { cmd := exec.Command("mkdir", "-p", "/etc/containers/certs.d/127.0.0.1:8089/") //nolint: gosec + _, err := cmd.Output() if err != nil { panic(err) @@ -41,6 +42,7 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { for _, file := range clientGlob { cmd = exec.Command("cp", file, "/etc/containers/certs.d/127.0.0.1:8089/") + res, err := cmd.CombinedOutput() if err != nil { panic(string(res)) @@ -49,6 +51,7 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { for _, file := range caGlob { cmd = exec.Command("cp", file, "/etc/containers/certs.d/127.0.0.1:8089/") + res, err := cmd.CombinedOutput() if err != nil { panic(string(res)) @@ -59,6 +62,7 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { for _, file := range allGlob { cmd = exec.Command("chmod", "a=rwx", file) + res, err := cmd.CombinedOutput() if err != nil { panic(string(res)) @@ -73,7 +77,9 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { caCertPool.AppendCertsFromPEM(caCert) resty.SetTLSClientConfig(&tls.Config{RootCAs: caCertPool, MinVersion: tls.VersionTLS12}) + defer func() { resty.SetTLSClientConfig(nil) }() + conf := config.New() conf.HTTP.Port = SecurePort2 conf.HTTP.TLS = &config.TLSConfig{ @@ -84,14 +90,17 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { ctlr := api.NewController(conf) ctlr.Config.Storage.RootDirectory = t.TempDir() + cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() Convey("Certs in privileged path", func() { configPath := makeConfigFile( fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s%s%s","showspinner":false}]}`, BaseSecureURL2, constants.RoutePrefix, constants.ExtCatalogPrefix)) + defer os.Remove(configPath) args := []string{"list", "--config", "imagetest"} @@ -100,6 +109,7 @@ func TestElevatedPrivilegesTLSNewControllerPrivilegedCert(t *testing.T) { imageCmd.SetOut(imageBuff) imageCmd.SetErr(imageBuff) imageCmd.SetArgs(args) + err := imageCmd.Execute() So(err, ShouldBeNil) }) diff --git a/pkg/cli/client/image_cmd_internal_test.go b/pkg/cli/client/image_cmd_internal_test.go index 242835a4..f4ec4228 100644 --- a/pkg/cli/client/image_cmd_internal_test.go +++ b/pkg/cli/client/image_cmd_internal_test.go @@ -35,26 +35,33 @@ import ( func TestSearchImageCmd(t *testing.T) { Convey("Test image help", t, func() { args := []string{"--help"} + configPath := makeConfigFile("") defer os.Remove(configPath) + cmd := NewImageCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) err := cmd.Execute() + So(buff.String(), ShouldContainSubstring, "Usage") So(err, ShouldBeNil) + Convey("with the shorthand", func() { args[0] = "-h" + configPath := makeConfigFile("") defer os.Remove(configPath) + cmd := NewImageCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) err := cmd.Execute() + So(buff.String(), ShouldContainSubstring, "Usage") So(err, ShouldBeNil) }) @@ -62,8 +69,10 @@ func TestSearchImageCmd(t *testing.T) { Convey("Test image no url", t, func() { args := []string{"name", "dummyIdRandom", "--config", "imagetest"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -97,6 +106,7 @@ func TestSearchImageCmd(t *testing.T) { if err != nil { panic(err) } + err = os.Setenv("HOME", home) if err != nil { log.Fatal(err) @@ -105,8 +115,10 @@ func TestSearchImageCmd(t *testing.T) { Convey("Test image no params", t, func() { args := []string{"--url", "someUrl"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -118,8 +130,10 @@ func TestSearchImageCmd(t *testing.T) { Convey("Test image invalid url", t, func() { args := []string{"name", "dummyImageName", "--url", "invalidUrl"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(searchService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -133,8 +147,10 @@ func TestSearchImageCmd(t *testing.T) { Convey("Test image invalid url port", t, func() { args := []string{"name", "dummyImageName", "--url", "http://localhost:99999"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(searchService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -146,8 +162,10 @@ func TestSearchImageCmd(t *testing.T) { Convey("without flags", func() { args := []string{"list", "--url", "http://localhost:99999"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(searchService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -161,8 +179,10 @@ func TestSearchImageCmd(t *testing.T) { Convey("Test image unreachable", t, func() { args := []string{"name", "dummyImageName", "--url", "http://localhost:9999"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(searchService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -174,8 +194,10 @@ func TestSearchImageCmd(t *testing.T) { Convey("Test image url from config", t, func() { args := []string{"name", "dummyImageName", "--config", "imagetest"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -191,8 +213,10 @@ func TestSearchImageCmd(t *testing.T) { Convey("Test image by name", t, func() { args := []string{"name", "dummyImageName", "--url", "http://127.0.0.1:8080"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","showspinner":false}]}`) defer os.Remove(configPath) + imageCmd := NewImageCommand(new(mockService)) buff := &bytes.Buffer{} imageCmd.SetOut(buff) @@ -233,8 +257,10 @@ func TestListRepos(t *testing.T) { Convey("Test listing repositories with debug flag", t, func() { args := []string{"list", "--config", "config-test", "--debug"} + configPath := makeConfigFile(`{"configs":[{"_name":"config-test","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewRepoCommand(new(searchService)) buff := bytes.NewBufferString("") @@ -272,6 +298,7 @@ func TestListRepos(t *testing.T) { if err != nil { panic(err) } + err = os.Setenv("HOME", home) if err != nil { log.Fatal(err) @@ -280,9 +307,11 @@ func TestListRepos(t *testing.T) { Convey("Test listing repositories error", t, func() { args := []string{"list", "--config", "config-test"} + configPath := makeConfigFile(`{"configs":[{"_name":"config-test", "url":"https://invalid.invalid","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewRepoCommand(new(searchService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -294,8 +323,10 @@ func TestListRepos(t *testing.T) { Convey("Test unable to get config value", t, func() { args := []string{"list", "--config", "config-test-nonexistent"} + configPath := makeConfigFile(`{"configs":[{"_name":"config-test","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewRepoCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -307,8 +338,10 @@ func TestListRepos(t *testing.T) { Convey("Test error - no url provided", t, func() { args := []string{"list", "--config", "config-test"} + configPath := makeConfigFile(`{"configs":[{"_name":"config-test","url":"","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewRepoCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -320,9 +353,11 @@ func TestListRepos(t *testing.T) { Convey("Test error - spinner config invalid", t, func() { args := []string{"list", "--config", "config-test"} + configPath := makeConfigFile(`{"configs":[{"_name":"config-test", "url":"https://test-url.com","showspinner":invalid}]}`) defer os.Remove(configPath) + cmd := NewRepoCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -334,9 +369,11 @@ func TestListRepos(t *testing.T) { Convey("Test error - verifyTLSConfig fails", t, func() { args := []string{"list", "--config", "config-test"} + configPath := makeConfigFile(`{"configs":[{"_name":"config-test", "verify-tls":"invalid", "url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewRepoCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -350,8 +387,10 @@ func TestListRepos(t *testing.T) { func TestOutputFormat(t *testing.T) { Convey("Test text", t, func() { args := []string{"name", "dummyImageName", "--config", "imagetest", "-f", "text"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -367,8 +406,10 @@ func TestOutputFormat(t *testing.T) { Convey("Test json", t, func() { args := []string{"name", "dummyImageName", "--config", "imagetest", "-f", "json"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -396,8 +437,10 @@ func TestOutputFormat(t *testing.T) { Convey("Test yaml", t, func() { args := []string{"name", "dummyImageName", "--config", "imagetest", "-f", "yaml"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -430,11 +473,13 @@ func TestOutputFormat(t *testing.T) { Convey("Test yml", func() { args := []string{"name", "dummyImageName", "--config", "imagetest", "-f", "yml"} + configPath := makeConfigFile( `{"configs":[{"_name":"imagetest",` + `"url":"https://test-url.com","showspinner":false}]}`, ) defer os.Remove(configPath) + cmd := NewImageCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -468,8 +513,10 @@ func TestOutputFormat(t *testing.T) { Convey("Test invalid", t, func() { args := []string{"name", "dummyImageName", "--config", "imagetest", "-f", "random"} + configPath := makeConfigFile(`{"configs":[{"_name":"imagetest","url":"https://test-url.com","showspinner":false}]}`) defer os.Remove(configPath) + cmd := NewImageCommand(new(mockService)) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -778,7 +825,6 @@ func TestImagesCommandGQL(t *testing.T) { configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, baseURL)) defer os.Remove(configPath) - args := []string{"cve", "repo:vuln", "--config", "imagetest"} cmd := NewImageCommand(mockService{}) buff := bytes.NewBufferString("") @@ -796,9 +842,11 @@ func TestImagesCommandGQL(t *testing.T) { Convey("CVE errors", func() { count := 0 + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, baseURL)) defer os.Remove(configPath) + args := []string{"cve", "repo:vuln", "--config", "imagetest"} cmd := NewImageCommand(mockService{ getCveByImageGQLFn: func(ctx context.Context, config SearchConfig, username, password, @@ -920,7 +968,6 @@ func TestImageCommandREST(t *testing.T) { configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, baseURL)) defer os.Remove(configPath) - args := []string{"base", "repo:derived", "--config", "imagetest"} cmd := NewImageCommand(NewSearchService()) buff := bytes.NewBufferString("") @@ -949,7 +996,6 @@ func TestImageCommandREST(t *testing.T) { configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, baseURL)) defer os.Remove(configPath) - args := []string{"digest", image.DigestStr(), "--config", "imagetest"} cmd := NewImageCommand(NewSearchService()) buff := bytes.NewBufferString("") @@ -969,7 +1015,6 @@ func TestImageCommandREST(t *testing.T) { configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, baseURL)) defer os.Remove(configPath) - args := []string{"list", "--config", "imagetest"} cmd := NewImageCommand(NewSearchService()) buff := bytes.NewBufferString("") @@ -994,7 +1039,6 @@ func TestImageCommandREST(t *testing.T) { configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, baseURL)) defer os.Remove(configPath) - args := []string{"name", "repo:img", "--config", "imagetest"} cmd := NewImageCommand(NewSearchService()) buff := bytes.NewBufferString("") @@ -1011,11 +1055,12 @@ func TestImageCommandREST(t *testing.T) { vulnImage := CreateDefaultVulnerableImage() err := UploadImage(vulnImage, baseURL, "repo", "vuln") So(err, ShouldBeNil) + args := []string{"cve", "repo:vuln", "--config", "imagetest"} configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, baseURL)) - args := []string{"cve", "repo:vuln", "--config", "imagetest"} defer os.Remove(configPath) + cmd := NewImageCommand(mockService{}) buff := bytes.NewBufferString("") cmd.SetOut(buff) diff --git a/pkg/cli/client/image_cmd_test.go b/pkg/cli/client/image_cmd_test.go index e7ba0735..5262cb48 100644 --- a/pkg/cli/client/image_cmd_test.go +++ b/pkg/cli/client/image_cmd_test.go @@ -11,6 +11,7 @@ import ( "os" "path" "regexp" + "strconv" "strings" "testing" "time" @@ -59,8 +60,10 @@ func TestSignature(t *testing.T) { } ctlr := api.NewController(conf) ctlr.Config.Storage.RootDirectory = currentDir + cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() image := CreateDefaultImage() @@ -135,6 +138,7 @@ func TestSignature(t *testing.T) { ctlr.Config.Storage.RootDirectory = currentDir cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() err = UploadImage(CreateDefaultImage(), url, repoName, "0.0.1") @@ -189,6 +193,7 @@ func TestSignature(t *testing.T) { ctlr.Config.Storage.RootDirectory = currentDir cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() err = UploadImage(CreateDefaultImage(), url, repoName, "0.0.1") @@ -257,9 +262,9 @@ func TestDerivedImageList(t *testing.T) { buff := &bytes.Buffer{} searchConfig.ResultWriter = buff err := client.SearchDerivedImageListGQL(searchConfig, "repo7:test:2.0") - actual := strings.TrimSpace(space.ReplaceAllString(buff.String(), " ")) So(err, ShouldBeNil) + actual := strings.TrimSpace(space.ReplaceAllString(buff.String(), " ")) So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 9d9461ed false 860B") }) @@ -353,17 +358,21 @@ func TestOutputFormatGQL(t *testing.T) { ctlr.Config.Storage.RootDirectory = t.TempDir() cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() err := uploadManifest(url) - t.Logf("%s", ctlr.Config.Storage.RootDirectory) So(err, ShouldBeNil) + t.Logf("%s", ctlr.Config.Storage.RootDirectory) + Convey("Test json", func() { t.Logf("%s", ctlr.Config.Storage.RootDirectory) args := []string{"name", "repo7", "--config", "imagetest", "-f", "json"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -408,8 +417,10 @@ func TestOutputFormatGQL(t *testing.T) { Convey("Test yaml", func() { args := []string{"name", "repo7", "--config", "imagetest", "-f", "yaml"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -457,8 +468,10 @@ func TestOutputFormatGQL(t *testing.T) { Convey("Test yml", func() { args := []string{"name", "repo7", "--config", "imagetest", "-f", "yml"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -506,8 +519,10 @@ func TestOutputFormatGQL(t *testing.T) { Convey("Test invalid", func() { args := []string{"name", "repo7", "--config", "imagetest", "-f", "random"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -534,17 +549,21 @@ func TestServerResponseGQL(t *testing.T) { ctlr.Config.Storage.RootDirectory = t.TempDir() cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() err := uploadManifest(url) + t.Logf("%s", ctlr.Config.Storage.RootDirectory) So(err, ShouldBeNil) Convey("Test all images config url", func() { t.Logf("%s", ctlr.Config.Storage.RootDirectory) args := []string{"list", "--config", "imagetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := &bytes.Buffer{} cmd.SetOut(buff) @@ -560,8 +579,10 @@ func TestServerResponseGQL(t *testing.T) { So(actual, ShouldContainSubstring, "repo7 test:1.0 linux/amd64 51e18f50 false 528B") Convey("Test all images invalid output format", func() { args := []string{"list", "--config", "imagetest", "-f", "random"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -575,8 +596,10 @@ func TestServerResponseGQL(t *testing.T) { Convey("Test all images verbose", func() { args := []string{"list", "--config", "imagetest", "--verbose"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -600,17 +623,22 @@ func TestServerResponseGQL(t *testing.T) { Convey("Test all images with debug flag", func() { args := []string{"list", "--config", "imagetest", "--debug"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() So(err, ShouldBeNil) + space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") + actual := strings.TrimSpace(str) So(actual, ShouldContainSubstring, "GET") So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") @@ -620,17 +648,22 @@ func TestServerResponseGQL(t *testing.T) { Convey("Test image by name config url", func() { args := []string{"name", "repo7", "--config", "imagetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err := cmd.Execute() So(err, ShouldBeNil) + space := regexp.MustCompile(`\s+`) str := space.ReplaceAllString(buff.String(), " ") + actual := strings.TrimSpace(str) So(actual, ShouldContainSubstring, "REPOSITORY TAG OS/ARCH DIGEST SIGNED SIZE") So(actual, ShouldContainSubstring, "repo7 test:2.0 linux/amd64 51e18f50 false 528B") @@ -638,8 +671,10 @@ func TestServerResponseGQL(t *testing.T) { Convey("invalid output format", func() { args := []string{"name", "repo7", "--config", "imagetest", "-f", "random"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -653,8 +688,10 @@ func TestServerResponseGQL(t *testing.T) { Convey("Test image by digest", func() { args := []string{"digest", "51e18f50", "--config", "imagetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -675,8 +712,10 @@ func TestServerResponseGQL(t *testing.T) { Convey("nonexistent digest", func() { args := []string{"digest", "d1g35t", "--config", "imagetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -689,8 +728,10 @@ func TestServerResponseGQL(t *testing.T) { Convey("invalid output format", func() { args := []string{"digest", "51e18f50", "--config", "imagetest", "-f", "random"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -704,8 +745,10 @@ func TestServerResponseGQL(t *testing.T) { Convey("Test image by name nonexistent name", func() { args := []string{"name", "repo777", "--config", "imagetest"} + configPath := makeConfigFile(fmt.Sprintf(`{"configs":[{"_name":"imagetest","url":"%s","showspinner":false}]}`, url)) defer os.Remove(configPath) + cmd := client.NewImageCommand(client.NewSearchService()) buff := bytes.NewBufferString("") cmd.SetOut(buff) @@ -782,7 +825,9 @@ func TestServerResponse(t *testing.T) { buff := &bytes.Buffer{} searchConfig.ResultWriter = buff searchConfig.Verbose = true + defer func() { searchConfig.Verbose = false }() + err := client.SearchAllImages(searchConfig) So(err, ShouldBeNil) @@ -1037,8 +1082,10 @@ func TestImagesSortFlag(t *testing.T) { cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err = cmd.Execute() So(err, ShouldBeNil) + str = buff.String() So(strings.Index(str, "b-repo"), ShouldBeLessThan, strings.Index(str, "a-repo")) @@ -1047,9 +1094,11 @@ func TestImagesSortFlag(t *testing.T) { cmd.SetOut(buff) cmd.SetErr(buff) cmd.SetArgs(args) + err = cmd.Execute() - str = buff.String() So(err, ShouldBeNil) + + str = buff.String() So(strings.Index(str, "b-repo"), ShouldBeLessThan, strings.Index(str, "a-repo")) }) } @@ -1130,7 +1179,7 @@ func uploadManifest(url string) error { _, _ = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -1236,7 +1285,7 @@ func uploadManifestDerivedBase(url string) error { _, _ = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). diff --git a/pkg/cli/client/search_cmd_test.go b/pkg/cli/client/search_cmd_test.go index 36ab1a0d..73608cfe 100644 --- a/pkg/cli/client/search_cmd_test.go +++ b/pkg/cli/client/search_cmd_test.go @@ -45,8 +45,10 @@ func TestReferrerCLI(t *testing.T) { } ctlr := api.NewController(conf) ctlr.Config.Storage.RootDirectory = rootDir + cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() repo := repoName @@ -144,6 +146,7 @@ func TestReferrerCLI(t *testing.T) { ctlr.Config.Storage.RootDirectory = rootDir cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() repo := repoName @@ -239,6 +242,7 @@ func TestFormatsReferrersCLI(t *testing.T) { ctlr.Config.Storage.RootDirectory = rootDir cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() repo := repoName @@ -443,6 +447,7 @@ func TestSearchCLI(t *testing.T) { ctlr.Config.Storage.RootDirectory = rootDir cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() const ( @@ -557,6 +562,7 @@ func TestFormatsSearchCLI(t *testing.T) { ctlr.Config.Storage.RootDirectory = rootDir cm := test.NewControllerManager(ctlr) cm.StartAndWait(conf.HTTP.Port) + defer cm.StopServer() const ( diff --git a/pkg/cli/client/server_info_cmd.go b/pkg/cli/client/server_info_cmd.go index e126d9f6..46aa3540 100644 --- a/pkg/cli/client/server_info_cmd.go +++ b/pkg/cli/client/server_info_cmd.go @@ -67,7 +67,7 @@ func GetServerStatus(config SearchConfig) error { switch { case errors.Is(err, zerr.ErrUnauthorizedAccess): serverInfo.Status = StatusUnknown - serverInfo.ErrorMsg = fmt.Sprintf("unauthorised access, %s", getCredentialsSuggestion(username)) + serverInfo.ErrorMsg = "unauthorised access, " + getCredentialsSuggestion(username) case errors.Is(err, zerr.ErrBadHTTPStatusCode), errors.Is(err, zerr.ErrURLNotFound): serverInfo.Status = StatusOffline serverInfo.ErrorMsg = fmt.Sprintf("%s: request at %s failed", zerr.ErrAPINotSupported.Error(), @@ -99,7 +99,7 @@ func GetServerStatus(config SearchConfig) error { serverInfo.ErrorMsg = fmt.Sprintf("%s%s endpoint is not available", constants.RoutePrefix, constants.ExtMgmt) case errors.Is(err, zerr.ErrUnauthorizedAccess): serverInfo.Status = StatusOnline - serverInfo.ErrorMsg = fmt.Sprintf("unauthorised access, %s", getCredentialsSuggestion(username)) + serverInfo.ErrorMsg = "unauthorised access, " + getCredentialsSuggestion(username) case errors.Is(err, zerr.ErrBadHTTPStatusCode): serverInfo.Status = StatusOnline serverInfo.ErrorMsg = fmt.Sprintf("%s: request at %s failed", zerr.ErrAPINotSupported.Error(), @@ -165,7 +165,7 @@ func (si *ServerInfo) ToText() (string, error) { output = serverStatus } else { - serverStatus := fmt.Sprintf("Server Status: %s", si.Status) + serverStatus := "Server Status: " + si.Status serverInfo := fmt.Sprintf("Server Version: %s\n"+ "Dist Spec Version: %s\n"+ "Built with: %s", diff --git a/pkg/cli/client/service.go b/pkg/cli/client/service.go index 41538ff8..5ebded38 100644 --- a/pkg/cli/client/service.go +++ b/pkg/cli/client/service.go @@ -113,8 +113,8 @@ func (service searchService) getDerivedImageListGQL(ctx context.Context, config }`, derivedImage, Flag2SortCriteria(config.SortBy)) result := &common.DerivedImageListResponse{} - err := service.makeGraphQLQuery(ctx, config, username, password, query, result) + err := service.makeGraphQLQuery(ctx, config, username, password, query, result) if errResult := checkResultGraphQLQuery(ctx, err, result.Errors); errResult != nil { return nil, errResult } @@ -261,8 +261,8 @@ func (service searchService) getBaseImageListGQL(ctx context.Context, config Sea }`, baseImage, Flag2SortCriteria(config.SortBy)) result := &common.BaseImageListResponse{} - err := service.makeGraphQLQuery(ctx, config, username, password, query, result) + err := service.makeGraphQLQuery(ctx, config, username, password, query, result) if errResult := checkResultGraphQLQuery(ctx, err, result.Errors); errResult != nil { return nil, errResult } @@ -298,7 +298,6 @@ func (service searchService) getImagesGQL(ctx context.Context, config SearchConf result := &common.ImageListResponse{} err := service.makeGraphQLQuery(ctx, config, username, password, query, result) - if errResult := checkResultGraphQLQuery(ctx, err, result.Errors); errResult != nil { return nil, errResult } @@ -334,7 +333,6 @@ func (service searchService) getImagesForDigestGQL(ctx context.Context, config S result := &common.ImagesForDigest{} err := service.makeGraphQLQuery(ctx, config, username, password, query, result) - if errResult := checkResultGraphQLQuery(ctx, err, result.Errors); errResult != nil { return nil, errResult } @@ -361,7 +359,6 @@ func (service searchService) getCveByImageGQL(ctx context.Context, config Search result := &cveResult{} err := service.makeGraphQLQuery(ctx, config, username, password, query, result) - if errResult := checkResultGraphQLQuery(ctx, err, result.Errors); errResult != nil { return nil, errResult } @@ -398,7 +395,6 @@ func (service searchService) getTagsForCVEGQL(ctx context.Context, config Search result := &common.ImagesForCve{} err := service.makeGraphQLQuery(ctx, config, username, password, query, result) - if errResult := checkResultGraphQLQuery(ctx, err, result.Errors); errResult != nil { return nil, errResult } @@ -448,7 +444,6 @@ func (service searchService) getFixedTagsForCVEGQL(ctx context.Context, config S result := &common.ImageListWithCVEFixedResponse{} err := service.makeGraphQLQuery(ctx, config, username, password, query, result) - if errResult := checkResultGraphQLQuery(ctx, err, result.Errors); errResult != nil { return nil, errResult } @@ -470,9 +465,9 @@ func (service searchService) getReferrers(ctx context.Context, config SearchConf } referrerResp := &ispec.Index{} + _, err = makeGETRequest(ctx, referrersEndpoint, username, password, config.VerifyTLS, config.Debug, &referrerResp, config.ResultWriter) - if err != nil { if common.IsContextDone(ctx) { return referrersResult{}, nil @@ -578,9 +573,9 @@ func getImage(ctx context.Context, config SearchConfig, username, password, imag } tagList := &tagListResp{} + _, err = makeGETRequest(ctx, tagListEndpoint, username, password, config.VerifyTLS, config.Debug, &tagList, config.ResultWriter) - if err != nil { if common.IsContextDone(ctx) { return @@ -881,7 +876,7 @@ func (cve cveResult) stringPlainText() string { id := ellipsize(cveListItem.ID, cveIDWidth, ellipsis) title := ellipsize(cveListItem.Title, cveTitleWidth, ellipsis) severity := ellipsize(cveListItem.Severity, cveSeverityWidth, ellipsis) - row := make([]string, 3) //nolint:gomnd + row := make([]string, 3) //nolint:mnd row[colCVEIDIndex] = id row[colCVESeverityIndex] = severity row[colCVETitleIndex] = title @@ -1236,7 +1231,7 @@ func addManifestToTable(table *tablewriter.Table, imageName, tagName string, man imgSize, _ := strconv.ParseUint(manifest.Size, 10, 64) size := ellipsize(strings.ReplaceAll(humanize.Bytes(imgSize), " ", ""), sizeWidth, ellipsis) isSigned := manifest.IsSigned - row := make([]string, 8) //nolint:gomnd + row := make([]string, 8) //nolint:mnd row[colImageNameIndex] = imageName row[colTagIndex] = tagName @@ -1264,7 +1259,7 @@ func addManifestToTable(table *tablewriter.Table, imageName, tagName string, man layerDigestStr := ellipsize(layerDigest.Encoded(), digestWidth, "") - layerRow := make([]string, 8) //nolint:gomnd + layerRow := make([]string, 8) //nolint:mnd layerRow[colImageNameIndex] = "" layerRow[colTagIndex] = "" layerRow[colDigestIndex] = "" diff --git a/pkg/cli/client/utils.go b/pkg/cli/client/utils.go index dc7a5752..433056b1 100644 --- a/pkg/cli/client/utils.go +++ b/pkg/cli/client/utils.go @@ -143,7 +143,7 @@ func printImageTableHeader(writer io.Writer, verbose bool, maxImageNameLen, maxT table.SetColMinWidth(colLayersIndex, layersWidth) } - row := make([]string, 8) //nolint:gomnd + row := make([]string, 8) //nolint:mnd // adding spaces so that repository and tag columns are aligned // in case the name/tag are fully shown and too long diff --git a/pkg/cli/client/utils_internal_test.go b/pkg/cli/client/utils_internal_test.go index 61f0cccb..3144c36b 100644 --- a/pkg/cli/client/utils_internal_test.go +++ b/pkg/cli/client/utils_internal_test.go @@ -63,7 +63,7 @@ func StartTestHTTPServer(routes HTTPRoutes, port string) *http.Server { } server := &http.Server{ //nolint:gosec - Addr: fmt.Sprintf(":%s", port), + Addr: ":" + port, Handler: mux, } @@ -81,6 +81,7 @@ func StartTestHTTPServer(routes HTTPRoutes, port string) *http.Server { func TestDoHTTPRequest(t *testing.T) { Convey("doHTTPRequest nil result pointer", t, func() { port := test.GetFreePort() + server := StartTestHTTPServer(nil, port) defer server.Close() @@ -105,6 +106,7 @@ func TestDoHTTPRequest(t *testing.T) { AllowedMethods: []string{http.MethodGet}, }, }, port) + defer server.Close() url := fmt.Sprintf("http://127.0.0.1:%s/test", port) diff --git a/pkg/cli/server/config_reloader_test.go b/pkg/cli/server/config_reloader_test.go index aa8f0f94..167abe46 100644 --- a/pkg/cli/server/config_reloader_test.go +++ b/pkg/cli/server/config_reloader_test.go @@ -87,6 +87,7 @@ func TestConfigReloader(t *testing.T) { // So(err, ShouldBeNil) os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -203,6 +204,7 @@ func TestConfigReloader(t *testing.T) { // So(err, ShouldBeNil) os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -321,6 +323,7 @@ func TestConfigReloader(t *testing.T) { // So(err, ShouldBeNil) os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -443,6 +446,7 @@ func TestConfigReloader(t *testing.T) { So(err, ShouldBeNil) os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -568,6 +572,7 @@ func TestConfigReloader(t *testing.T) { // So(err, ShouldBeNil) os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) diff --git a/pkg/cli/server/extensions_test.go b/pkg/cli/server/extensions_test.go index 5546473f..5fe75fdc 100644 --- a/pkg/cli/server/extensions_test.go +++ b/pkg/cli/server/extensions_test.go @@ -62,6 +62,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { So(err, ShouldBeNil) os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(cli.NewServerRootCmd().Execute(), ShouldNotBeNil) content = fmt.Sprintf(`{ @@ -101,6 +102,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { So(err, ShouldBeNil) os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(cli.NewServerRootCmd().Execute(), ShouldNotBeNil) }) @@ -108,6 +110,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := fmt.Sprintf(`{"storage":{"rootDirectory":"%s", "storageDriver": {"name": "s3"}}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -118,6 +121,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { err = tmpfile.Close() So(err, ShouldBeNil) os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(cli.NewServerRootCmd().Execute(), ShouldNotBeNil) }) @@ -125,6 +129,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := fmt.Sprintf(`{"storage":{"rootDirectory":"%s"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -134,7 +139,9 @@ func TestVerifyExtensionsConfig(t *testing.T) { So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(cli.NewServerRootCmd().Execute(), ShouldBeNil) }) @@ -142,6 +149,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := fmt.Sprintf(`{"storage":{"rootDirectory":"%s"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -152,7 +160,9 @@ func TestVerifyExtensionsConfig(t *testing.T) { So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(cli.NewServerRootCmd().Execute(), ShouldNotBeNil) }) @@ -160,6 +170,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := fmt.Sprintf(`{"storage":{"rootDirectory":"%s"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -171,6 +182,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { err = tmpfile.Close() So(err, ShouldBeNil) os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(cli.NewServerRootCmd().Execute(), ShouldNotBeNil) }) @@ -178,6 +190,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := fmt.Sprintf(`{"storage":{"rootDirectory":"%s"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -197,6 +210,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := fmt.Sprintf(`{"storage":{"rootDirectory":"%s"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -216,6 +230,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := fmt.Sprintf(`{"storage":{"rootDirectory":"%s"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -226,6 +241,7 @@ func TestVerifyExtensionsConfig(t *testing.T) { err = tmpfile.Close() So(err, ShouldBeNil) os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(cli.NewServerRootCmd().Execute(), ShouldNotBeNil) }) } @@ -235,7 +251,9 @@ func TestValidateExtensionsConfig(t *testing.T) { config := config.New() tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) + content := []byte(`{ "storage": { "rootDirectory": "%/tmp/zot" @@ -264,9 +282,12 @@ func TestValidateExtensionsConfig(t *testing.T) { Convey("Test missing extensions for UI to work", t, func(c C) { config := config.New() + tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) + content := []byte(`{ "storage": { "rootDirectory": "%/tmp/zot" @@ -294,6 +315,7 @@ func TestValidateExtensionsConfig(t *testing.T) { config := config.New() tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) content := []byte(`{ @@ -326,6 +348,7 @@ func TestValidateExtensionsConfig(t *testing.T) { config := config.New() tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) content := []byte(`{ @@ -374,7 +397,9 @@ func TestServeExtensions(t *testing.T) { baseURL := GetBaseURL(port) logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + tmpFile := t.TempDir() content := fmt.Sprintf(`{ @@ -394,12 +419,14 @@ func TestServeExtensions(t *testing.T) { cfgfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.WriteString(content) So(err, ShouldBeNil) err = cfgfile.Close() So(err, ShouldBeNil) os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { Convey("run", t, func() { err = cli.NewServerRootCmd().Execute() @@ -408,7 +435,9 @@ func TestServeExtensions(t *testing.T) { }() WaitTillServerReady(baseURL) + data, err := os.ReadFile(logFile.Name()) + So(err, ShouldBeNil) So(string(data), ShouldContainSubstring, "\"Extensions\":null") }) @@ -418,7 +447,9 @@ func TestServeExtensions(t *testing.T) { baseURL := GetBaseURL(port) logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + tmpFile := t.TempDir() content := fmt.Sprintf(`{ @@ -440,6 +471,7 @@ func TestServeExtensions(t *testing.T) { cfgfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.WriteString(content) So(err, ShouldBeNil) err = cfgfile.Close() @@ -476,6 +508,7 @@ func testWithMetricsEnabled(t *testing.T, rootDir string, cfgContentFormat strin So(err, ShouldBeNil) defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.WriteString(content) So(err, ShouldBeNil) err = cfgfile.Close() @@ -589,6 +622,7 @@ func TestServeMetricsExtension(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) tmpFile := t.TempDir() + defer os.Remove(logFile.Name()) // clean up content := fmt.Sprintf(`{ @@ -613,18 +647,21 @@ func TestServeMetricsExtension(t *testing.T) { cfgfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(cfgfile.Name()) // clean up + _, err = cfgfile.WriteString(content) So(err, ShouldBeNil) err = cfgfile.Close() So(err, ShouldBeNil) os.Args = []string{"cli_test", "serve", cfgfile.Name()} + go func() { Convey("run", t, func() { err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) }) }() + WaitTillServerReady(baseURL) resp, err := resty.R().Get(baseURL + "/metrics") @@ -684,7 +721,9 @@ func TestServeSyncExtension(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + So(string(data), ShouldContainSubstring, "\"Extensions\":{\"Search\":null,\"Sync\":{\"Enable\":true") }) @@ -730,7 +769,9 @@ func TestServeSyncExtension(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + So(string(data), ShouldContainSubstring, "\"Extensions\":{\"Search\":null,\"Sync\":{\"Enable\":true") }) @@ -766,7 +807,9 @@ func TestServeSyncExtension(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + So(string(data), ShouldContainSubstring, "\"Extensions\":{\"Search\":null,\"Sync\":{\"Enable\":false") }) @@ -800,7 +843,9 @@ func TestServeScrubExtension(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + dataStr := string(data) So(dataStr, ShouldContainSubstring, "\"Extensions\":{\"Search\":null,\"Sync\":null,\"Metrics\":null,\"Scrub\":{\"Enable\":true,\"Interval\":86400000000000},\"Lint\":null") //nolint:lll // gofumpt conflicts with lll @@ -832,7 +877,9 @@ func TestServeScrubExtension(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + // Even if in config we specified scrub interval=1h, the minimum interval is 2h dataStr := string(data) So(dataStr, ShouldContainSubstring, "\"Scrub\":{\"Enable\":true,\"Interval\":3600000000000}") @@ -864,7 +911,9 @@ func TestServeScrubExtension(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + dataStr := string(data) So(dataStr, ShouldContainSubstring, "\"Extensions\":{\"Search\":null,\"Sync\":null,\"Metrics\":null,\"Scrub\":{\"Enable\":true,\"Interval\":86400000000000},\"Lint\":null") //nolint:lll // gofumpt conflicts with lll @@ -896,7 +945,9 @@ func TestServeScrubExtension(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + dataStr := string(data) So(dataStr, ShouldContainSubstring, "\"Scrub\":{\"Enable\":false,\"Interval\":86400000000000}") So(dataStr, ShouldContainSubstring, "scrub config not provided, skipping scrub") @@ -935,7 +986,9 @@ func TestServeLintExtension(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + So(string(data), ShouldContainSubstring, "\"Extensions\":{\"Search\":null,\"Sync\":null,\"Metrics\":null,\"Scrub\":null,\"Lint\":{\"Enable\":true,\"MandatoryAnnotations\":") //nolint:lll // gofumpt conflicts with lll }) @@ -964,7 +1017,9 @@ func TestServeLintExtension(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + So(string(data), ShouldContainSubstring, "\"Extensions\":{\"Search\":null,\"Sync\":null,\"Metrics\":null,\"Scrub\":null,\"Lint\":{\"Enable\":false,\"MandatoryAnnotations\":null}") //nolint:lll // gofumpt conflicts with lll }) @@ -1045,7 +1100,9 @@ func TestServeSearchEnabledCVE(t *testing.T) { tempDir := t.TempDir() logPath, err := runCLIWithConfig(tempDir, content) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + // to avoid data race when multiple go routines write to trivy DB instance. WaitTillTrivyDBDownloadStarted(tempDir) @@ -1100,6 +1157,7 @@ func TestServeSearchEnabledNoCVE(t *testing.T) { tempDir := t.TempDir() logPath, err := runCLIWithConfig(tempDir, content) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up substring := `"Extensions":{"Search":{"Enable":true,"CVE":null}` //nolint:lll // gofumpt conflicts with lll @@ -1148,7 +1206,9 @@ func TestServeSearchDisabled(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + dataStr := string(data) So(dataStr, ShouldContainSubstring, `"Search":{"Enable":false,"CVE":{"UpdateInterval":10800000000000,"Trivy":null}`) @@ -1186,6 +1246,7 @@ func TestServeMgmtExtension(t *testing.T) { logPath, err := runCLIWithConfig(t.TempDir(), content) So(err, ShouldBeNil) defer os.Remove(logPath) // clean up + found, err := ReadLogFileAndSearchString(logPath, "setting up mgmt routes", 10*time.Second) if !found { @@ -1218,6 +1279,7 @@ func TestServeMgmtExtension(t *testing.T) { logPath, err := runCLIWithConfig(t.TempDir(), content) So(err, ShouldBeNil) defer os.Remove(logPath) // clean up + found, err := ReadLogFileAndSearchString(logPath, "skip enabling the mgmt route as the config prerequisites are not met", 10*time.Second) @@ -1249,6 +1311,7 @@ func TestServeMgmtExtension(t *testing.T) { logPath, err := runCLIWithConfig(t.TempDir(), content) So(err, ShouldBeNil) defer os.Remove(logPath) // clean up + found, err := ReadLogFileAndSearchString(logPath, "skip enabling the mgmt route as the config prerequisites are not met", 10*time.Second) @@ -1291,6 +1354,7 @@ func TestServeImageTrustExtension(t *testing.T) { logPath, err := runCLIWithConfig(t.TempDir(), content) So(err, ShouldBeNil) defer os.Remove(logPath) // clean up + found, err := ReadLogFileAndSearchString(logPath, "skip enabling the image trust routes as the config prerequisites are not met", 10*time.Second) @@ -1327,6 +1391,7 @@ func TestServeImageTrustExtension(t *testing.T) { logPath, err := runCLIWithConfig(t.TempDir(), content) So(err, ShouldBeNil) defer os.Remove(logPath) // clean up + found, err := ReadLogFileAndSearchString(logPath, "skip enabling the image trust routes as the config prerequisites are not met", 10*time.Second) @@ -1365,6 +1430,7 @@ func TestServeImageTrustExtension(t *testing.T) { logPath, err := runCLIWithConfig(t.TempDir(), content) So(err, ShouldBeNil) defer os.Remove(logPath) // clean up + found, err := ReadLogFileAndSearchString(logPath, "setting up image trust routes", 10*time.Second) @@ -1400,6 +1466,7 @@ func TestOverlappingSyncRetentionConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := `{ "distSpecVersion": "1.1.0", "storage": { @@ -1458,7 +1525,9 @@ func TestOverlappingSyncRetentionConfig(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + So(string(data), ShouldNotContainSubstring, "overlapping sync content") }) @@ -1466,6 +1535,7 @@ func TestOverlappingSyncRetentionConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := `{ "distSpecVersion": "1.1.0", "storage": { @@ -1522,7 +1592,9 @@ func TestOverlappingSyncRetentionConfig(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + So(string(data), ShouldContainSubstring, "overlapping sync content\":{\"Prefix\":\"infra/*") }) @@ -1530,6 +1602,7 @@ func TestOverlappingSyncRetentionConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := `{ "distSpecVersion": "1.1.0", "storage": { @@ -1584,7 +1657,9 @@ func TestOverlappingSyncRetentionConfig(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + So(string(data), ShouldContainSubstring, "overlapping sync content\":{\"Prefix\":\"**") }) @@ -1592,6 +1667,7 @@ func TestOverlappingSyncRetentionConfig(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) defer os.Remove(tmpfile.Name()) // clean up + content := `{ "distSpecVersion": "1.1.0", "storage": { @@ -1649,7 +1725,9 @@ func TestOverlappingSyncRetentionConfig(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + So(string(data), ShouldContainSubstring, "overlapping sync content\":{\"Prefix\":\"prod/*") }) } @@ -1714,7 +1792,9 @@ func TestSyncWithRemoteStorageConfig(t *testing.T) { data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up + So(string(data), ShouldNotContainSubstring, "using both sync and remote storage features needs config.Extensions.Sync.DownloadDir to be specified") }) @@ -1723,11 +1803,14 @@ func TestSyncWithRemoteStorageConfig(t *testing.T) { port := GetFreePort() logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := fmt.Sprintf(`{ "distSpecVersion": "1.1.0", "storage": { @@ -1781,7 +1864,9 @@ func TestSyncWithRemoteStorageConfig(t *testing.T) { data, err := os.ReadFile(logFile.Name()) So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up + So(string(data), ShouldContainSubstring, "using both sync and remote storage features needs config.Extensions.Sync.DownloadDir to be specified") }) @@ -1790,11 +1875,14 @@ func TestSyncWithRemoteStorageConfig(t *testing.T) { port := GetFreePort() logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + defer os.Remove(logFile.Name()) // clean up tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := fmt.Sprintf(`{ "distSpecVersion": "1.1.0", "storage": { @@ -1853,6 +1941,7 @@ func TestSyncWithRemoteStorageConfig(t *testing.T) { data, err := os.ReadFile(logFile.Name()) So(err, ShouldBeNil) defer os.Remove(logFile.Name()) // clean up + So(string(data), ShouldContainSubstring, "using both sync and remote storage features needs config.Extensions.Sync.DownloadDir to be specified") }) diff --git a/pkg/cli/server/root.go b/pkg/cli/server/root.go index 46f16b0d..95336f7d 100644 --- a/pkg/cli/server/root.go +++ b/pkg/cli/server/root.go @@ -590,6 +590,7 @@ func applyDefaultValues(config *config.Config, viperInstance *viper.Viper, log z defaultDBDownloadURL := "ghcr.io/aquasecurity/trivy-db" log.Info().Str("url", defaultDBDownloadURL).Str("component", "config"). Msg("using default trivy-db download URL.") + config.Extensions.Search.CVE.Trivy.DBRepository = defaultDBDownloadURL } @@ -597,6 +598,7 @@ func applyDefaultValues(config *config.Config, viperInstance *viper.Viper, log z defaultJavaDBDownloadURL := "ghcr.io/aquasecurity/trivy-java-db" log.Info().Str("url", defaultJavaDBDownloadURL).Str("component", "config"). Msg("using default trivy-java-db download URL.") + config.Extensions.Search.CVE.Trivy.JavaDBRepository = defaultJavaDBDownloadURL } } @@ -618,7 +620,7 @@ func applyDefaultValues(config *config.Config, viperInstance *viper.Viper, log z } if config.Extensions.Scrub.Interval == 0 { - config.Extensions.Scrub.Interval = 24 * time.Hour //nolint: gomnd + config.Extensions.Scrub.Interval = 24 * time.Hour //nolint:mnd } } @@ -651,7 +653,7 @@ func applyDefaultValues(config *config.Config, viperInstance *viper.Viper, log z // apply deleteUntagged default for idx := range config.Storage.Retention.Policies { - if !viperInstance.IsSet("storage::retention::policies::" + fmt.Sprint(idx) + "::deleteUntagged") { + if !viperInstance.IsSet("storage::retention::policies::" + strconv.Itoa(idx) + "::deleteUntagged") { config.Storage.Retention.Policies[idx].DeleteUntagged = &defaultVal } } @@ -720,7 +722,9 @@ func applyDefaultValues(config *config.Config, viperInstance *viper.Viper, log z // apply deleteUntagged default for idx := range storageConfig.Retention.Policies { - deleteUntaggedKey := "storage::subpaths::" + name + "::retention::policies::" + fmt.Sprint(idx) + "::deleteUntagged" + deleteUntaggedKey := fmt.Sprintf("storage::subpaths::%s::retention::policies::%d::deleteUntagged", + name, idx, + ) if !viperInstance.IsSet(deleteUntaggedKey) { storageConfig.Retention.Policies[idx].DeleteUntagged = &defaultVal } diff --git a/pkg/cli/server/root_test.go b/pkg/cli/server/root_test.go index 9e7fab4e..9a993ed3 100644 --- a/pkg/cli/server/root_test.go +++ b/pkg/cli/server/root_test.go @@ -122,12 +122,15 @@ func TestVerify(t *testing.T) { Convey("Test verify bad config", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"log":{}}`) _, err = tmpfile.Write(content) So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -136,7 +139,9 @@ func TestVerify(t *testing.T) { Convey("Test verify config with no extension", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion":"1.1.0","storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot"}, "log":{"level":"debug"}}`) @@ -144,6 +149,7 @@ func TestVerify(t *testing.T) { So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -152,7 +158,9 @@ func TestVerify(t *testing.T) { Convey("Test verify config with dotted config name", t, func(c C) { tmpfile, err := os.CreateTemp("", ".zot-test*") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(` distspecversion: 1.1.0 http: @@ -168,6 +176,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -566,7 +575,9 @@ storage: Convey("Test verify with bad gc retention repo patterns", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{ "distSpecVersion": "1.1.0", "storage": { @@ -607,14 +618,18 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(cli.NewServerRootCmd().Execute(), ShouldNotBeNil) }) Convey("Test verify with bad gc image retention tag regex", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{ "distSpecVersion": "1.1.0", "storage": { @@ -647,7 +662,9 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} + So(cli.NewServerRootCmd().Execute(), ShouldNotBeNil) }) @@ -710,7 +727,9 @@ storage: Convey("Test verify storage driver different than s3", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot", "storageDriver": {"name": "gcs"}}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) @@ -718,6 +737,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -726,7 +746,9 @@ storage: Convey("Test verify subpath storage driver different than s3", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot", "storageDriver": {"name": "s3"}, "subPaths": {"/a": {"rootDirectory": "/zot-a","storageDriver": {"name": "gcs"}}}}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", @@ -735,6 +757,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -743,13 +766,16 @@ storage: Convey("Test verify subpath storage config", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot", "subPaths": {"/a": {"rootDirectory": "/zot-a"},"/b": {"rootDirectory": "/zot-a"}}}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) err = os.WriteFile(tmpfile.Name(), content, 0o0600) So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -762,6 +788,7 @@ storage: "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) err = os.WriteFile(tmpfile.Name(), content, 0o0600) So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -773,6 +800,7 @@ storage: "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) err = os.WriteFile(tmpfile.Name(), content, 0o0600) So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -784,6 +812,7 @@ storage: "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) err = os.WriteFile(tmpfile.Name(), content, 0o0600) So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -795,6 +824,7 @@ storage: "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) err = os.WriteFile(tmpfile.Name(), content, 0o0600) So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -806,6 +836,7 @@ storage: "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) err = os.WriteFile(tmpfile.Name(), content, 0o0600) So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -817,6 +848,7 @@ storage: "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}}`) err = os.WriteFile(tmpfile.Name(), content, 0o0600) So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -825,7 +857,9 @@ storage: Convey("Test verify w/ authorization and w/o authentication", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "accessControl":{"repositories":{},"adminPolicy":{"users":["admin"], @@ -834,6 +868,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -842,7 +877,9 @@ storage: Convey("Test verify w/ authorization and w/ authentication", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}, @@ -852,6 +889,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -860,7 +898,9 @@ storage: Convey("Test verify anonymous authorization", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "accessControl":{"repositories":{"**":{"anonymousPolicy": ["read", "create"]}, @@ -870,6 +910,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -878,7 +919,9 @@ storage: Convey("Test verify admin policy authz is not allowed if no authn is configured", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "accessControl":{ @@ -896,6 +939,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -904,7 +948,9 @@ storage: Convey("Test verify default policy authz is not allowed if no authn is configured", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "accessControl":{ @@ -918,6 +964,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -926,7 +973,9 @@ storage: Convey("Test verify authz per user policies fail if no authn is configured", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "accessControl":{ @@ -945,6 +994,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -953,7 +1003,9 @@ storage: Convey("Test verify w/ sync and w/o filesystem storage", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot", "storageDriver": {"name": "s3"}}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -963,6 +1015,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -971,7 +1024,9 @@ storage: Convey("Test verify w/ sync and w/ filesystem storage", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -981,6 +1036,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -989,7 +1045,9 @@ storage: Convey("Test verify with bad sync prefixes", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -1000,6 +1058,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1008,7 +1067,9 @@ storage: Convey("Test verify with bad sync content config", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -1019,6 +1080,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1027,7 +1089,9 @@ storage: Convey("Test verify with good sync content config", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -1038,6 +1102,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -1046,7 +1111,9 @@ storage: Convey("Test verify with bad authorization repo patterns", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}, @@ -1055,6 +1122,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1063,7 +1131,9 @@ storage: Convey("Test verify sync config default tls value", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -1074,6 +1144,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -1082,7 +1153,9 @@ storage: Convey("Test verify sync without retry options", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"htpasswd":{"path":"test/data/htpasswd"},"failDelay":1}}, @@ -1092,6 +1165,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1100,7 +1174,9 @@ storage: Convey("Test verify config with unknown keys", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion": "1.0.0", "storage": {"rootDirectory": "/tmp/zot"}, "http": {"url": "127.0.0.1", "port": "8080"}, "log": {"level": "debug"}}`) @@ -1108,6 +1184,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1116,7 +1193,9 @@ storage: Convey("Test verify openid config with missing parameter", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion":"1.1.0","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"}}}}}, @@ -1125,6 +1204,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1133,7 +1213,9 @@ storage: Convey("Test verify oauth2 config with missing parameter", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion":"1.1.0","storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"openid":{"providers":{"github":{"clientid":"client_id"}}}}}, @@ -1142,6 +1224,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1150,7 +1233,9 @@ storage: Convey("Test verify openid config with unsupported provider", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion":"1.1.0","storage":{"rootDirectory":"/tmp/zot"}, "http":{"address":"127.0.0.1","port":"8080","realm":"zot", "auth":{"openid":{"providers":{"unsupported":{"issuer":"http://127.0.0.1:5556/dex"}}}}}, @@ -1159,6 +1244,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1167,7 +1253,9 @@ storage: Convey("Test verify openid config without apikey extension enabled", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion":"1.1.0","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", @@ -1177,6 +1265,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -1185,7 +1274,9 @@ storage: Convey("Test verify config with missing basedn key", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion": "1.0.0", "storage": {"rootDirectory": "/tmp/zot"}, "http": {"auth": {"ldap": {"address": "ldap", "userattribute": "uid"}}, "address": "127.0.0.1", "port": "8080"}, @@ -1194,6 +1285,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1202,7 +1294,9 @@ storage: Convey("Test verify config with missing address key", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion": "1.0.0", "storage": {"rootDirectory": "/tmp/zot"}, "http": {"auth": {"ldap": {"basedn": "ou=Users,dc=example,dc=org", "userattribute": "uid"}}, "address": "127.0.0.1", "port": "8080"}, @@ -1211,6 +1305,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1219,7 +1314,9 @@ storage: Convey("Test verify config with missing userattribute key", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion": "1.0.0", "storage": {"rootDirectory": "/tmp/zot"}, "http": {"auth": {"ldap": {"basedn": "ou=Users,dc=example,dc=org", "address": "ldap"}}, "address": "127.0.0.1", "port": "8080"}, @@ -1228,6 +1325,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1236,7 +1334,9 @@ storage: Convey("Test verify good config", t, func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"distSpecVersion": "1.0.0", "storage": {"rootDirectory": "/tmp/zot"}, "http": {"address": "127.0.0.1", "port": "8080"}, "log": {"level": "debug"}}`) @@ -1244,6 +1344,7 @@ storage: So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "verify", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldBeNil) @@ -1446,6 +1547,7 @@ func TestApiKeyConfig(t *testing.T) { config := config.New() tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) content := []byte(`{"distSpecVersion":"1.1.0","storage":{"rootDirectory":"/tmp/zot"}, @@ -1466,6 +1568,7 @@ func TestApiKeyConfig(t *testing.T) { config := config.New() tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) content := []byte(`{"distSpecVersion":"1.1.0","storage":{"rootDirectory":"/tmp/zot"}, @@ -1484,6 +1587,7 @@ func TestApiKeyConfig(t *testing.T) { config := config.New() tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) content := []byte(`{"distSpecVersion":"1.1.0","storage":{"rootDirectory":"/tmp/zot"}, @@ -1527,6 +1631,7 @@ func TestServeAPIKey(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up So(string(data), ShouldContainSubstring, "\"APIKey\":true") }) @@ -1553,6 +1658,7 @@ func TestServeAPIKey(t *testing.T) { So(err, ShouldBeNil) data, err := os.ReadFile(logPath) So(err, ShouldBeNil) + defer os.Remove(logPath) // clean up So(string(data), ShouldContainSubstring, "\"APIKey\":false") }) @@ -1568,7 +1674,9 @@ func TestLoadConfig(t *testing.T) { config := config.New() tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) + content := []byte(`{"storage":{"rootDirectory":"/tmp/zot", "subPaths": {"/a": {"rootDirectory": "/tmp/zot","dedupe":"true","gc":"true","gcDelay":"1s","gcInterval":"1s"}, "/b": {"rootDirectory": "/zot-a","dedupe":"true","gc":"true","gcDelay":"1s"}}}, @@ -1634,6 +1742,7 @@ func TestLoadConfig(t *testing.T) { config := config.New() tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) content := []byte(`{"storage":{"rootDirectory":"/tmp/zot", @@ -1812,12 +1921,15 @@ func TestScrub(t *testing.T) { Convey("bad config", func(c C) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(`{"log":{}}`) _, err = tmpfile.Write(content) So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "scrub", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1837,7 +1949,9 @@ func TestScrub(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(fmt.Sprintf(`{ "storage": { "rootDirectory": "%s" @@ -1867,7 +1981,9 @@ func TestScrub(t *testing.T) { tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(fmt.Sprintf(`{ "storage": { "rootDirectory": "" @@ -1884,6 +2000,7 @@ func TestScrub(t *testing.T) { So(err, ShouldBeNil) err = tmpfile.Close() So(err, ShouldBeNil) + os.Args = []string{"cli_test", "scrub", tmpfile.Name()} err = cli.NewServerRootCmd().Execute() So(err, ShouldNotBeNil) @@ -1901,27 +2018,29 @@ func TestScrub(t *testing.T) { panic(err) } - if err := os.MkdirAll(fmt.Sprintf("%s/blobs", repo), 0o755); err != nil { + if err := os.MkdirAll(repo+"/blobs", 0o755); err != nil { panic(err) } - if _, err = os.Stat(fmt.Sprintf("%s/oci-layout", repo)); err != nil { + if _, err = os.Stat(repo + "/oci-layout"); err != nil { content := []byte(`{"imageLayoutVersion": "1.0.0"}`) - if err = os.WriteFile(fmt.Sprintf("%s/oci-layout", repo), content, 0o600); err != nil { + if err = os.WriteFile(repo+"/oci-layout", content, 0o600); err != nil { panic(err) } } - if _, err = os.Stat(fmt.Sprintf("%s/index.json", repo)); err != nil { + if _, err = os.Stat(repo + "/index.json"); err != nil { content := []byte(`not a JSON content`) - if err = os.WriteFile(fmt.Sprintf("%s/index.json", repo), content, 0o600); err != nil { + if err = os.WriteFile(repo+"/index.json", content, 0o600); err != nil { panic(err) } } tmpfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(tmpfile.Name()) // clean up + content := []byte(fmt.Sprintf(`{ "storage": { "rootDirectory": "%s" diff --git a/pkg/cli/server/stress_test.go b/pkg/cli/server/stress_test.go index e749b443..7ef2c2c5 100644 --- a/pkg/cli/server/stress_test.go +++ b/pkg/cli/server/stress_test.go @@ -52,6 +52,7 @@ func TestStressTooManyOpenFiles(t *testing.T) { if err != nil { t.Logf("error when reading zot log file:\n%s\n", err) } + t.Logf("\n\n Zot log file content:\n%s\n", string(data)) os.Remove(logFile.Name()) }() @@ -67,6 +68,7 @@ func TestStressTooManyOpenFiles(t *testing.T) { if err != nil { t.Logf("error when listing storage files:\n%s\n", err) } + t.Logf("Listing Storage root FS:\n%s\n", out) }() @@ -94,6 +96,7 @@ func TestStressTooManyOpenFiles(t *testing.T) { cfgfile, err := os.CreateTemp("", "zot-test*.json") So(err, ShouldBeNil) + defer os.Remove(cfgfile.Name()) // clean up _, err = cfgfile.WriteString(content) So(err, ShouldBeNil) @@ -104,10 +107,12 @@ func TestStressTooManyOpenFiles(t *testing.T) { "copy", "--format=oci", "--insecure-policy", "--dest-tls-verify=false", "docker://public.ecr.aws/zomato/alpine:3.11.3", fmt.Sprintf("oci:%s:alpine", dir), } + out, err := exec.Command("skopeo", skopeoArgs...).Output() if err != nil { t.Logf("\nerror on skopeo copy:\n%s\n", err) } + So(err, ShouldBeNil) t.Logf("\nCopy test image locally:\n%s\n", out) @@ -122,6 +127,7 @@ func TestStressTooManyOpenFiles(t *testing.T) { worker(i, port, dir) }() } + wg.Wait() _, err = setMaxOpenFilesLimit(initialLimit) @@ -142,6 +148,7 @@ func TestStressTooManyOpenFiles(t *testing.T) { if err != nil { t.Logf("error when reading zot scrub file:\n%s\n", err) } + t.Logf("\n\n Zot scrub file content:\n%s\n", string(data)) os.Remove(scrubFile.Name()) }() @@ -170,6 +177,7 @@ func worker(id int, zotPort, rootDir string) { "copy", "--format=oci", "--insecure-policy", "--dest-tls-verify=false", sourceImg, destImg, } + err := exec.Command("skopeo", skopeoArgs...).Run() if err != nil { //nolint: wsl continue // we expect clients to receive errors due to FD limit reached on server diff --git a/pkg/common/common_test.go b/pkg/common/common_test.go index 3d7b5e9e..a6c0f7c3 100644 --- a/pkg/common/common_test.go +++ b/pkg/common/common_test.go @@ -46,10 +46,12 @@ func TestCommon(t *testing.T) { Convey("test dirExists()", t, func() { exists := common.DirExists("testdir") So(exists, ShouldBeFalse) + tempDir := t.TempDir() file, err := os.Create(path.Join(tempDir, "file.txt")) So(err, ShouldBeNil) + isDir := common.DirExists(file.Name()) So(isDir, ShouldBeFalse) }) @@ -75,6 +77,7 @@ func TestCommon(t *testing.T) { So(err, ShouldBeNil) So(localSockets, ShouldNotBeEmpty) So(localSockets, ShouldContain, "127.0.0.1:8765") + for _, socket := range localSockets { lastColonIndex := strings.LastIndex(socket, ":") So(socket[lastColonIndex+1:], ShouldEqual, "8765") @@ -86,6 +89,7 @@ func TestCommon(t *testing.T) { So(err, ShouldBeNil) So(localSockets, ShouldNotBeEmpty) So(localSockets, ShouldContain, "[::1]:8766") + for _, socket := range localSockets { lastColonIndex := strings.LastIndex(socket, ":") So(socket[lastColonIndex+1:], ShouldEqual, "8766") @@ -94,9 +98,10 @@ func TestCommon(t *testing.T) { Convey("Test GetIPFromHostName with valid hostname", t, func() { addrs, err := common.GetIPFromHostName("github.com") + + // we can't check the actual addresses here as they can change So(err, ShouldBeNil) So(addrs, ShouldNotBeEmpty) - // we can't check the actual addresses here as they can change }) Convey("Test GetIPFromHostName with non-existent hostname", t, func() { diff --git a/pkg/common/http_client.go b/pkg/common/http_client.go index 8d8f76a5..58c77252 100644 --- a/pkg/common/http_client.go +++ b/pkg/common/http_client.go @@ -39,7 +39,6 @@ func loadPerHostCerts(caCertPool *x509.CertPool, host string) *tls.Config { if DirExists(clientCertsDir) { tlsConfig, err := GetTLSConfig(clientCertsDir, caCertPool) - if err == nil { return tlsConfig } @@ -49,7 +48,6 @@ func loadPerHostCerts(caCertPool *x509.CertPool, host string) *tls.Config { clientCertsDir = filepath.Join(certsPath, host) if DirExists(clientCertsDir) { tlsConfig, err := GetTLSConfig(clientCertsDir, caCertPool) - if err == nil { return tlsConfig } diff --git a/pkg/compliance/v1_0_0/check.go b/pkg/compliance/v1_0_0/check.go index b0a49a75..6436987f 100644 --- a/pkg/compliance/v1_0_0/check.go +++ b/pkg/compliance/v1_0_0/check.go @@ -39,7 +39,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { defer outputJSONExit() } - baseURL := fmt.Sprintf("http://%s", net.JoinHostPort(config.Address, config.Port)) + baseURL := "http://" + net.JoinHostPort(config.Address, config.Port) storageInfo := config.StorageInfo @@ -62,6 +62,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) So(resp.String(), ShouldNotBeEmpty) So(resp.Header().Get("Content-Type"), ShouldEqual, constants.DefaultMediaType) + var repoList api.RepositoryList err = json.Unmarshal(resp.Body(), &repoList) So(err, ShouldBeNil) @@ -84,6 +85,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { So(resp.String(), ShouldNotBeEmpty) result, ok := resp.Result().(*api.RepositoryList) So(ok, ShouldBeTrue) + if !config.Compliance { // stricter check for zot ci/cd So(len(result.Repositories), ShouldBeGreaterThan, 0) @@ -107,6 +109,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { resp, err = resty.R().Get(baseURL + "/v2/repo1/tags/list") So(err, ShouldBeNil) + if !config.Compliance { // stricter check for zot ci/cd So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -128,6 +131,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { resp, err = resty.R().Get(baseURL + "/v2/repo2/tags/list") So(err, ShouldBeNil) + if !config.Compliance { // stricter check for zot ci/cd So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -138,6 +142,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { content := []byte("this is a blob1") digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) + resp, err = resty.R().Put(loc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) @@ -221,6 +226,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { resp, err = resty.R().Get(baseURL + "/v2/repo10/repo20/repo30/tags/list") So(err, ShouldBeNil) + if !config.Compliance { // stricter check for zot ci/cd So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -231,6 +237,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { content := []byte("this is a blob3") digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) + resp, err = resty.R().Put(loc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) @@ -271,6 +278,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { So(loc, ShouldNotBeEmpty) var buf bytes.Buffer + chunk1 := []byte("this is the first chunk1") nbytes, err := buf.Write(chunk1) So(nbytes, ShouldEqual, len(chunk1)) @@ -315,6 +323,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusCreated) blobLoc := test.Location(baseURL, resp) + So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusCreated) So(blobLoc, ShouldNotBeEmpty) @@ -339,6 +348,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { So(loc, ShouldNotBeEmpty) var buf bytes.Buffer + chunk1 := []byte("this is the first chunk2") nbytes, err := buf.Write(chunk1) So(nbytes, ShouldEqual, len(chunk1)) @@ -383,6 +393,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusCreated) blobLoc := test.Location(baseURL, resp) + So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusCreated) So(blobLoc, ShouldNotBeEmpty) @@ -466,6 +477,7 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { resp, err = resty.R().Get(loc) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNoContent) + content := []byte("this is a blob5") digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) @@ -606,9 +618,11 @@ func CheckWorkflows(t *testing.T, config *compliance.Config) { if strings.HasPrefix(nextURL, "<") || strings.HasPrefix(nextURL, "\"") { nextURL = nextURL[1:] } + if strings.HasSuffix(nextURL, ">") || strings.HasSuffix(nextURL, "\"") { nextURL = nextURL[:len(nextURL)-1] } + nextURL = baseURL + nextURL resp, err = resty.R().Get(nextURL) diff --git a/pkg/debug/pprof/pprof_test.go b/pkg/debug/pprof/pprof_test.go index f5166de3..787eedba 100644 --- a/pkg/debug/pprof/pprof_test.go +++ b/pkg/debug/pprof/pprof_test.go @@ -31,6 +31,7 @@ func TestProfilingAuthz(t *testing.T) { testCreds := test.GetCredString(adminUsername, adminPassword) + test.GetCredString(username, password) htpasswdPath := test.MakeHtpasswdFileFromString(testCreds) + defer os.Remove(htpasswdPath) conf := config.New() @@ -41,6 +42,7 @@ func TestProfilingAuthz(t *testing.T) { ctlr := api.NewController(conf) cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // unauthenticated clients should have access to /v2/ @@ -103,6 +105,7 @@ func TestProfilingAuthz(t *testing.T) { ctlr.Log.Info().Int64("seedUser", seedUser).Int64("seedPass", seedPass).Msg("random seed for username & password") cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // unauthenticated clients should not have access to /v2/ @@ -160,6 +163,7 @@ func TestProfilingAuthz(t *testing.T) { ctlr := api.NewController(conf) cm := test.NewControllerManager(ctlr) cm.StartAndWait(port) + defer cm.StopServer() // unauthenticated clients should have access to /v2/ diff --git a/pkg/exporter/api/controller_test.go b/pkg/exporter/api/controller_test.go index 16c31ed9..7fade424 100644 --- a/pkg/exporter/api/controller_test.go +++ b/pkg/exporter/api/controller_test.go @@ -93,6 +93,7 @@ func TestNewExporter(t *testing.T) { Convey("Make an exporter controller", t, func() { exporterConfig := api.DefaultConfig() So(exporterConfig, ShouldNotBeNil) + exporterPort := GetFreePort() serverPort := GetFreePort() exporterConfig.Exporter.Port = exporterPort @@ -131,6 +132,7 @@ func TestNewExporter(t *testing.T) { Convey("When zot server is running", func() { servercConfig := zotcfg.New() So(servercConfig, ShouldNotBeNil) + baseURL := fmt.Sprintf(BaseURL, serverPort) servercConfig.HTTP.Port = serverPort servercConfig.BinaryType = "minimal" @@ -140,6 +142,7 @@ func TestNewExporter(t *testing.T) { So(serverController, ShouldNotBeNil) dir := t.TempDir() + serverController.Config.Storage.RootDirectory = dir go func(ctrl *zotapi.Controller) { if err := ctrl.Init(); err != nil { @@ -151,6 +154,7 @@ func TestNewExporter(t *testing.T) { panic(err) } }(serverController) + defer func(ctrl *zotapi.Controller) { _ = ctrl.Server.Shutdown(context.TODO()) }(serverController) @@ -160,6 +164,7 @@ func TestNewExporter(t *testing.T) { if err == nil { break } + time.Sleep(SleepTime) } @@ -223,10 +228,12 @@ func TestNewExporter(t *testing.T) { if err != nil { panic(err) } + reqsSize := int(nBig.Int64()) for i := 0; i < reqsSize; i++ { monitoring.IncDownloadCounter(serverController.Metrics, "dummyrepo") } + time.Sleep(SleepTime) go func() { @@ -303,16 +310,19 @@ func TestNewExporter(t *testing.T) { }) Convey("Collecting data: Test that concurent Summary observation requests works properly", func() { var latencySum float64 + nBig, err := rand.Int(rand.Reader, big.NewInt(1000)) if err != nil { panic(err) } + reqsSize := int(nBig.Int64()) for i := 0; i < reqsSize; i++ { latency := getRandomLatency() latencySum += latency.Seconds() monitoring.ObserveHTTPRepoLatency(serverController.Metrics, "/v2/dummyrepo/manifests/testreference", latency) } + time.Sleep(SleepTime) go func() { @@ -372,6 +382,7 @@ func TestNewExporter(t *testing.T) { err = pmMetric.Write(&metric) So(err, ShouldBeNil) + if latency.Seconds() < fvalue { So(*metric.Counter.Value, ShouldEqual, 1) } else { @@ -415,6 +426,7 @@ func TestNewExporter(t *testing.T) { err = pmMetric.Write(&metric) So(err, ShouldBeNil) + if latency.Seconds() < fvalue { So(*metric.Counter.Value, ShouldEqual, 1) } else { @@ -440,9 +452,11 @@ func TestNewExporter(t *testing.T) { latency = time.Duration(pvalue*float64(time.Second)) + getRandomLatencyN(int64(dBuckets[0]*float64(time.Second))) } + latencySum += latency.Seconds() monitoring.ObserveHTTPMethodLatency(serverController.Metrics, "GET", latency) } + time.Sleep(SleepTime) go func() { @@ -489,11 +503,14 @@ func TestNewExporter(t *testing.T) { if err != nil { panic(err) } + workersSize := int(nBig.Int64()) for i := 0; i < workersSize; i++ { wg.Add(1) + go func() { defer wg.Done() + m := serverController.Metrics.ReceiveMetrics() json := jsoniter.ConfigCompatibleWithStandardLibrary @@ -503,6 +520,7 @@ func TestNewExporter(t *testing.T) { } }() } + wg.Wait() }) Convey("Negative testing: Increment a counter that does not exist", func() { diff --git a/pkg/exporter/api/exporter.go b/pkg/exporter/api/exporter.go index 251faf76..2f477c46 100644 --- a/pkg/exporter/api/exporter.go +++ b/pkg/exporter/api/exporter.go @@ -171,7 +171,7 @@ func GetCollector(c *Controller) *Collector { } func runExporter(c *Controller) { - exporterAddr := fmt.Sprintf(":%s", c.Config.Exporter.Port) + exporterAddr := ":" + c.Config.Exporter.Port server := &http.Server{ Addr: exporterAddr, IdleTimeout: idleTimeout, diff --git a/pkg/extensions/extension_image_trust.go b/pkg/extensions/extension_image_trust.go index 78692829..cdfcfb65 100644 --- a/pkg/extensions/extension_image_trust.go +++ b/pkg/extensions/extension_image_trust.go @@ -175,8 +175,8 @@ func SetupImageTrustExtension(conf *config.Config, metaDB mTypes.MetaDB, log log if conf.Storage.RemoteCache { endpoint, _ := conf.Storage.CacheDriver["endpoint"].(string) region, _ := conf.Storage.CacheDriver["region"].(string) - imgTrustStore, err = imagetrust.NewAWSImageTrustStore(region, endpoint) + imgTrustStore, err = imagetrust.NewAWSImageTrustStore(region, endpoint) if err != nil { return err } diff --git a/pkg/extensions/extension_image_trust_test.go b/pkg/extensions/extension_image_trust_test.go index 6ba6c18b..bbdb3f76 100644 --- a/pkg/extensions/extension_image_trust_test.go +++ b/pkg/extensions/extension_image_trust_test.go @@ -6,6 +6,7 @@ package extensions_test import ( "context" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -42,7 +43,7 @@ import ( type errReader int func (errReader) Read(p []byte) (int, error) { - return 0, fmt.Errorf("test error") //nolint:goerr113 + return 0, errors.New("test error") //nolint:goerr113 } func TestSignatureHandlers(t *testing.T) { @@ -179,6 +180,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ conf := config.New() conf.HTTP.Port = port + if cacheDriverParams != nil { conf.Storage.CacheDriver = cacheDriverParams } @@ -251,7 +253,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ options.KeyOpts{KeyRef: path.Join(keyDir, "cosign.key"), PassFunc: generate.GetPass}, options.SignOptions{ Registry: options.RegistryOptions{AllowInsecure: true}, - AnnotationOptions: options.AnnotationOptions{Annotations: []string{fmt.Sprintf("tag=%s", tag)}}, + AnnotationOptions: options.AnnotationOptions{Annotations: []string{"tag=" + tag}}, Upload: true, }, []string{fmt.Sprintf("localhost:%s/%s@%s", port, repo, image.DigestStr())}) @@ -299,6 +301,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ conf := config.New() conf.HTTP.Port = port + if cacheDriverParams != nil { conf.Storage.CacheDriver = cacheDriverParams } @@ -353,7 +356,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ So(err, ShouldBeNil) // upload the certificate - certificateContent, err := os.ReadFile(path.Join(rootDir, "notation/localkeys", fmt.Sprintf("%s.crt", certName))) + certificateContent, err := os.ReadFile(path.Join(rootDir, "notation/localkeys", certName+".crt")) So(err, ShouldBeNil) So(certificateContent, ShouldNotBeNil) @@ -402,6 +405,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ conf := config.New() conf.HTTP.Port = port + if cacheDriverParams != nil { conf.Storage.CacheDriver = cacheDriverParams } @@ -486,7 +490,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ So(err, ShouldBeNil) // upload the certificate - certificateContent, err := os.ReadFile(path.Join(rootDir, "notation/localkeys", fmt.Sprintf("%s.crt", certName))) + certificateContent, err := os.ReadFile(path.Join(rootDir, "notation/localkeys", certName+".crt")) So(err, ShouldBeNil) So(certificateContent, ShouldNotBeNil) @@ -564,6 +568,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ conf := config.New() conf.HTTP.Port = port + if cacheDriverParams != nil { conf.Storage.CacheDriver = cacheDriverParams } @@ -666,7 +671,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ options.KeyOpts{KeyRef: path.Join(keyDir, "cosign.key"), PassFunc: generate.GetPass}, options.SignOptions{ Registry: options.RegistryOptions{AllowInsecure: true}, - AnnotationOptions: options.AnnotationOptions{Annotations: []string{fmt.Sprintf("tag=%s", tag)}}, + AnnotationOptions: options.AnnotationOptions{Annotations: []string{"tag=" + tag}}, Upload: true, }, []string{fmt.Sprintf("localhost:%s/%s@%s", port, repo, image.DigestStr())}) @@ -729,6 +734,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ globalDir := t.TempDir() port := test.GetFreePort() testCreds := test.GetCredString("admin", "admin") + "\n" + test.GetCredString("test", "test") + htpasswdPath := test.MakeHtpasswdFileFromString(testCreds) defer os.Remove(htpasswdPath) @@ -741,6 +747,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ Actions: []string{}, }, } + if cacheDriverParams != nil { conf.Storage.CacheDriver = cacheDriverParams } @@ -825,6 +832,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ conf := config.New() conf.HTTP.Port = port + if cacheDriverParams != nil { conf.Storage.CacheDriver = cacheDriverParams } @@ -856,14 +864,16 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ // Write image image := CreateRandomImage() + err = WriteImageToFileSystem(image, repo, tag, storeController) So(err, ShouldBeNil) // Write signature sig := CreateImageWith().RandomLayers(1, 2).RandomConfig().Build() - So(err, ShouldBeNil) + ref, err := signature.GetCosignSignatureTagForManifest(image.Manifest) So(err, ShouldBeNil) + err = WriteImageToFileSystem(sig, repo, ref, storeController) So(err, ShouldBeNil) @@ -874,6 +884,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ ctlrManager := test.NewControllerManager(ctlr) ctlrManager.StartAndWait(port) + defer ctlrManager.StopServer() strQuery := fmt.Sprintf(imageQuery, repo, tag) @@ -929,6 +940,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ conf := config.New() conf.HTTP.Port = port + if cacheDriverParams != nil { conf.Storage.CacheDriver = cacheDriverParams } @@ -985,6 +997,7 @@ func RunSignatureUploadAndVerificationTests(t *testing.T, cacheDriverParams map[ // Make sure the write to disk fails So(os.Chmod(globalDir, 0o000), ShouldBeNil) + defer func() { So(os.Chmod(globalDir, 0o755), ShouldBeNil) }() diff --git a/pkg/extensions/extension_scrub.go b/pkg/extensions/extension_scrub.go index 553fcc26..37278261 100644 --- a/pkg/extensions/extension_scrub.go +++ b/pkg/extensions/extension_scrub.go @@ -68,7 +68,7 @@ func (gen *taskGenerator) Next() (scheduler.Task, error) { if repo == "" { gen.done = true - return nil, nil + return nil, nil //nolint:nilnil } gen.lastRepo = repo diff --git a/pkg/extensions/extension_ui_test.go b/pkg/extensions/extension_ui_test.go index b4c39991..c011589b 100644 --- a/pkg/extensions/extension_ui_test.go +++ b/pkg/extensions/extension_ui_test.go @@ -31,6 +31,7 @@ func TestUIExtension(t *testing.T) { // stdout and a file logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt") So(err, ShouldBeNil) + logPath := logFile.Name() defer os.Remove(logPath) diff --git a/pkg/extensions/extension_userprefs_test.go b/pkg/extensions/extension_userprefs_test.go index 6db5ec2a..85c30e79 100644 --- a/pkg/extensions/extension_userprefs_test.go +++ b/pkg/extensions/extension_userprefs_test.go @@ -73,11 +73,13 @@ func TestHandlers(t *testing.T) { extensions.PutStar(response, request, mockmetaDB, log) res := response.Result() So(res.StatusCode, ShouldEqual, http.StatusBadRequest) + defer res.Body.Close() extensions.PutBookmark(response, request, mockmetaDB, log) res = response.Result() So(res.StatusCode, ShouldEqual, http.StatusBadRequest) + defer res.Body.Close() }) @@ -88,11 +90,13 @@ func TestHandlers(t *testing.T) { extensions.PutStar(response, request, mockmetaDB, log) res := response.Result() So(res.StatusCode, ShouldEqual, http.StatusNotFound) + defer res.Body.Close() extensions.PutBookmark(response, request, mockmetaDB, log) res = response.Result() So(res.StatusCode, ShouldEqual, http.StatusNotFound) + defer res.Body.Close() }) @@ -111,15 +115,19 @@ func TestHandlers(t *testing.T) { response := httptest.NewRecorder() extensions.PutBookmark(response, request, mockmetaDB, log) + res := response.Result() - So(res.StatusCode, ShouldEqual, http.StatusNotFound) defer res.Body.Close() + So(res.StatusCode, ShouldEqual, http.StatusNotFound) + response = httptest.NewRecorder() extensions.PutStar(response, request, mockmetaDB, log) + res = response.Result() - So(res.StatusCode, ShouldEqual, http.StatusNotFound) defer res.Body.Close() + + So(res.StatusCode, ShouldEqual, http.StatusNotFound) }) Convey("ErrUserDataNotAllowed", func() { @@ -137,15 +145,19 @@ func TestHandlers(t *testing.T) { response := httptest.NewRecorder() extensions.PutBookmark(response, request, mockmetaDB, log) + res := response.Result() - So(res.StatusCode, ShouldEqual, http.StatusForbidden) defer res.Body.Close() + So(res.StatusCode, ShouldEqual, http.StatusForbidden) + response = httptest.NewRecorder() extensions.PutStar(response, request, mockmetaDB, log) + res = response.Result() - So(res.StatusCode, ShouldEqual, http.StatusForbidden) defer res.Body.Close() + + So(res.StatusCode, ShouldEqual, http.StatusForbidden) }) Convey("ErrUnexpectedError", func() { @@ -162,15 +174,19 @@ func TestHandlers(t *testing.T) { } response := httptest.NewRecorder() extensions.PutBookmark(response, request, mockmetaDB, log) + res := response.Result() - So(res.StatusCode, ShouldEqual, http.StatusInternalServerError) defer res.Body.Close() + So(res.StatusCode, ShouldEqual, http.StatusInternalServerError) + response = httptest.NewRecorder() extensions.PutStar(response, request, mockmetaDB, log) + res = response.Result() - So(res.StatusCode, ShouldEqual, http.StatusInternalServerError) defer res.Body.Close() + + So(res.StatusCode, ShouldEqual, http.StatusInternalServerError) }) }) } diff --git a/pkg/extensions/extensions_test.go b/pkg/extensions/extensions_test.go index dc61cf90..66086523 100644 --- a/pkg/extensions/extensions_test.go +++ b/pkg/extensions/extensions_test.go @@ -5,7 +5,6 @@ package extensions_test import ( "encoding/json" - "fmt" "net/http" "net/url" "os" @@ -51,6 +50,7 @@ func TestEnableExtension(t *testing.T) { So(err, ShouldBeNil) conf.Log.Level = "info" conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // cleanup ctlr := api.NewController(conf) @@ -87,6 +87,7 @@ func TestMetricsExtension(t *testing.T) { } conf.Log.Level = "info" conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // cleanup ctlr := api.NewController(conf) @@ -146,6 +147,7 @@ func TestMgmtExtension(t *testing.T) { defer func() { conf.HTTP.Auth.HTPasswd.Path = "" + os.Remove(htpasswdPath) }() @@ -177,6 +179,7 @@ func TestMgmtExtension(t *testing.T) { found, err := test.ReadLogFileAndSearchString(logFile.Name(), "setting up mgmt routes", mgmtReadyTimeout) So(err, ShouldBeNil) + defer func() { if !found { data, err := os.ReadFile(logFile.Name()) @@ -363,6 +366,7 @@ func TestMgmtExtension(t *testing.T) { defer func() { conf.HTTP.Auth.HTPasswd.Path = "" + os.Remove(htpasswdPath) }() @@ -448,6 +452,7 @@ func TestMgmtExtension(t *testing.T) { defer func() { conf.HTTP.Auth.HTPasswd.Path = "" + os.Remove(htpasswdPath) }() @@ -733,6 +738,7 @@ func TestMgmtExtension(t *testing.T) { defer func() { conf.HTTP.Auth.HTPasswd.Path = "" + os.Remove(htpasswdPath) }() @@ -865,6 +871,7 @@ func TestMgmtWithBearer(t *testing.T) { Convey("Make a new controller", t, func() { authorizedNamespace := "allowedrepo" unauthorizedNamespace := "notallowedrepo" + authTestServer := authutils.MakeAuthTestServer(ServerKey, unauthorizedNamespace) defer authTestServer.Close() @@ -915,19 +922,21 @@ func TestMgmtWithBearer(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var goodToken authutils.AccessTokenResponse + err = json.Unmarshal(resp.Body(), &goodToken) So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) resp, err = resty.R().SetHeader("Authorization", - fmt.Sprintf("Bearer %s", goodToken.AccessToken)).Options(baseURL + "/v2/") + "Bearer "+goodToken.AccessToken).Options(baseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNoContent) @@ -949,7 +958,7 @@ func TestMgmtWithBearer(t *testing.T) { So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Post(baseURL + "/v2/" + authorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -969,12 +978,14 @@ func TestMgmtWithBearer(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var badToken authutils.AccessTokenResponse + err = json.Unmarshal(resp.Body(), &badToken) So(err, ShouldBeNil) resp, err = resty.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", badToken.AccessToken)). + SetHeader("Authorization", "Bearer "+badToken.AccessToken). Post(baseURL + "/v2/" + unauthorizedNamespace + "/blobs/uploads/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) diff --git a/pkg/extensions/get_extensions_disabled_test.go b/pkg/extensions/get_extensions_disabled_test.go index 92d1facc..203c974b 100644 --- a/pkg/extensions/get_extensions_disabled_test.go +++ b/pkg/extensions/get_extensions_disabled_test.go @@ -37,7 +37,9 @@ func TestGetExensionsDisabled(t *testing.T) { logFile, err := os.CreateTemp("", "zot-log*.txt") So(err, ShouldBeNil) + conf.Log.Output = logFile.Name() + defer os.Remove(logFile.Name()) // clean up ctlr := makeController(conf, t.TempDir()) diff --git a/pkg/extensions/imagetrust/image_trust.go b/pkg/extensions/imagetrust/image_trust.go index e9f256d2..a6e35000 100644 --- a/pkg/extensions/imagetrust/image_trust.go +++ b/pkg/extensions/imagetrust/image_trust.go @@ -18,7 +18,7 @@ import ( "github.com/aws/aws-sdk-go/aws/session" smanager "github.com/aws/aws-sdk-go/service/secretsmanager" "github.com/aws/aws-secretsmanager-caching-go/secretcache" - smithy "github.com/aws/smithy-go" + "github.com/aws/smithy-go" godigest "github.com/opencontainers/go-digest" ispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -225,7 +225,7 @@ func (gen *sigValidityTaskGenerator) Next() (scheduler.Task, error) { gen.log.Info().Msg("finished generating tasks for updating signatures validity") - return nil, nil + return nil, nil //nolint:nilnil } return NewValidityTask(gen.metaDB, gen.repos[gen.repoIndex], gen.log), nil diff --git a/pkg/extensions/imagetrust/image_trust_test.go b/pkg/extensions/imagetrust/image_trust_test.go index 87f1e430..7fb307cf 100644 --- a/pkg/extensions/imagetrust/image_trust_test.go +++ b/pkg/extensions/imagetrust/image_trust_test.go @@ -19,7 +19,7 @@ import ( awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http" "github.com/aws/aws-sdk-go-v2/service/secretsmanager" "github.com/aws/aws-sdk-go-v2/service/secretsmanager/types" - smithy "github.com/aws/smithy-go" + "github.com/aws/smithy-go" smithyhttp "github.com/aws/smithy-go/transport/http" guuid "github.com/gofrs/uuid" "github.com/notaryproject/notation-go" @@ -267,7 +267,7 @@ func TestVerifySignatures(t *testing.T) { options.KeyOpts{KeyRef: path.Join(cosignDir, "cosign.key"), PassFunc: generate.GetPass}, options.SignOptions{ Registry: options.RegistryOptions{AllowInsecure: true}, - AnnotationOptions: options.AnnotationOptions{Annotations: []string{fmt.Sprintf("tag=%s", tag)}}, + AnnotationOptions: options.AnnotationOptions{Annotations: []string{"tag=" + tag}}, Upload: true, }, []string{fmt.Sprintf("localhost:%s/%s@%s", port, repo, image.DigestStr())}) @@ -280,11 +280,14 @@ func TestVerifySignatures(t *testing.T) { So(err, ShouldBeNil) var index ispec.Index + err = json.Unmarshal(indexContent, &index) So(err, ShouldBeNil) - var rawSignature []byte - var sigKey string + var ( + rawSignature []byte + sigKey string + ) for _, manifest := range index.Manifests { if manifest.Digest != image.Digest() { @@ -460,11 +463,14 @@ func TestVerifySignatures(t *testing.T) { So(err, ShouldBeNil) var index ispec.Index + err = json.Unmarshal(indexContent, &index) So(err, ShouldBeNil) - var rawSignature []byte - var sigKey string + var ( + rawSignature []byte + sigKey string + ) for _, manifest := range index.Manifests { if manifest.Digest != image.Digest() { @@ -1182,6 +1188,7 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) { rootDir := t.TempDir() logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt") So(err, ShouldBeNil) + logPath := logFile.Name() defer os.Remove(logPath) @@ -1246,7 +1253,7 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) { options.KeyOpts{KeyRef: path.Join(keyDir, "cosign.key"), PassFunc: generate.GetPass}, options.SignOptions{ Registry: options.RegistryOptions{AllowInsecure: true}, - AnnotationOptions: options.AnnotationOptions{Annotations: []string{fmt.Sprintf("tag=%s", tag)}}, + AnnotationOptions: options.AnnotationOptions{Annotations: []string{"tag=" + tag}}, Upload: true, }, []string{fmt.Sprintf("localhost:%s/%s@%s", port, repo, image.DigestStr())}) @@ -1256,11 +1263,14 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) { So(err, ShouldBeNil) var index ispec.Index + err = json.Unmarshal(indexContent, &index) So(err, ShouldBeNil) - var rawSignature []byte - var sigKey string + var ( + rawSignature []byte + sigKey string + ) for _, manifest := range index.Manifests { if manifest.Digest != image.Digest() { @@ -1347,8 +1357,10 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) { err = json.Unmarshal(indexContent, &index) So(err, ShouldBeNil) - var rawSignature []byte - var sigKey string + var ( + rawSignature []byte + sigKey string + ) for _, manifest := range index.Manifests { blobContent, err := ctlr.StoreController.DefaultStore.GetBlobContent(repo, manifest.Digest) @@ -1360,6 +1372,7 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) { So(err, ShouldBeNil) t.Logf("Processing manifest %v", notationSig) + if notationSig.Config.MediaType != notreg.ArtifactTypeNotation || notationSig.Subject.Digest != image.Digest() { continue @@ -1379,8 +1392,8 @@ func RunVerificationTests(t *testing.T, dbDriverParams map[string]interface{}) { certificateContent, err := os.ReadFile( path.Join(notationDir, - fmt.Sprintf("notation/truststore/x509/ca/%s", certName), - fmt.Sprintf("%s.crt", certName), + "notation/truststore/x509/ca/"+certName, + certName+".crt", ), ) So(err, ShouldBeNil) diff --git a/pkg/extensions/imagetrust/notation.go b/pkg/extensions/imagetrust/notation.go index c5c3d4ad..744491c9 100644 --- a/pkg/extensions/imagetrust/notation.go +++ b/pkg/extensions/imagetrust/notation.go @@ -189,7 +189,6 @@ func (cloud *CertificateAWSStorage) InitTrustpolicy(trustpolicy []byte) error { } _, err = cloud.secretsManagerClient.DeleteSecret(context.Background(), deleteSecretParam) - if err != nil { return err } @@ -210,7 +209,6 @@ func (cloud *CertificateAWSStorage) recreateSecret(secretInputParam *secretsmana for i := 0; i < maxAttempts; i++ { _, err = cloud.secretsManagerClient.CreateSecret(context.Background(), secretInputParam) - if err == nil { return nil } @@ -494,7 +492,6 @@ func (cloud *CertificateAWSStorage) StoreCertificate( } _, err := cloud.secretsManagerClient.CreateSecret(context.Background(), secretInputParam) - if err != nil && IsResourceExistsException(err) { return nil } @@ -540,6 +537,7 @@ func parseAndValidateCertificateContent(certificateContent []byte) ([]*x509.Cert if err != nil { return []*x509.Certificate{}, false, fmt.Errorf("%w: %w", zerr.ErrInvalidCertificateContent, err) } + certs = append(certs, cert) block, rest = pem.Decode(rest) } diff --git a/pkg/extensions/lint/lint_test.go b/pkg/extensions/lint/lint_test.go index 88402605..7187ffab 100644 --- a/pkg/extensions/lint/lint_test.go +++ b/pkg/extensions/lint/lint_test.go @@ -9,6 +9,7 @@ import ( "net/http" "os" "path" + "strconv" "testing" godigest "github.com/opencontainers/go-digest" @@ -60,7 +61,9 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) manifestBlob := resp.Body() + var manifest ispec.Manifest + err = json.Unmarshal(manifestBlob, &manifest) So(err, ShouldBeNil) @@ -106,7 +109,9 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) manifestBlob := resp.Body() + var manifest ispec.Manifest + err = json.Unmarshal(manifestBlob, &manifest) So(err, ShouldBeNil) @@ -152,7 +157,9 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) manifestBlob := resp.Body() + var manifest ispec.Manifest + err = json.Unmarshal(manifestBlob, &manifest) So(err, ShouldBeNil) @@ -204,7 +211,9 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) manifestBlob := resp.Body() + var manifest ispec.Manifest + err = json.Unmarshal(manifestBlob, &manifest) So(err, ShouldBeNil) @@ -221,7 +230,9 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) configBlob := resp.Body() + var imageConfig ispec.Image + err = json.Unmarshal(configBlob, &imageConfig) So(err, ShouldBeNil) @@ -239,13 +250,13 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { // upload image config blob resp, err = resty.R(). - Post(fmt.Sprintf("%s/v2/zot-test/blobs/uploads/", baseURL)) + Post(baseURL + "/v2/zot-test/blobs/uploads/") So(err, ShouldBeNil) loc := test.Location(baseURL, resp) _, err = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(configContent))). + SetHeader("Content-Length", strconv.Itoa(len(configContent))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", configBlobDigestRaw.String()). SetBody(configContent). @@ -290,12 +301,13 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) manifestBlob := resp.Body() + var manifest ispec.Manifest + err = json.Unmarshal(manifestBlob, &manifest) So(err, ShouldBeNil) manifest.Annotations = make(map[string]string) - manifest.Annotations["annotation1"] = "testFail1" configDigest := manifest.Config.Digest @@ -306,7 +318,9 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) configBlob := resp.Body() + var imageConfig ispec.Image + err = json.Unmarshal(configBlob, &imageConfig) So(err, ShouldBeNil) @@ -324,13 +338,13 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { // upload image config blob _, err = resty.R(). - Post(fmt.Sprintf("%s/v2/zot-test/blobs/uploads/", baseURL)) + Post(baseURL + "/v2/zot-test/blobs/uploads/") So(err, ShouldBeNil) loc := test.Location(baseURL, resp) _, err = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(configContent))). + SetHeader("Content-Length", strconv.Itoa(len(configContent))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", configBlobDigestRaw.String()). SetBody(configContent). @@ -375,7 +389,9 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) manifestBlob := resp.Body() + var manifest ispec.Manifest + err = json.Unmarshal(manifestBlob, &manifest) So(err, ShouldBeNil) @@ -430,7 +446,9 @@ func TestVerifyMandatoryAnnotations(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) manifestBlob := resp.Body() + var manifest ispec.Manifest + err = json.Unmarshal(manifestBlob, &manifest) So(err, ShouldBeNil) diff --git a/pkg/extensions/monitoring/common.go b/pkg/extensions/monitoring/common.go index 917e3228..5968e43f 100644 --- a/pkg/extensions/monitoring/common.go +++ b/pkg/extensions/monitoring/common.go @@ -23,6 +23,7 @@ func GetDirSize(path string) (int64, error) { if err != nil { return err } + if !info.IsDir() { size += info.Size() } diff --git a/pkg/extensions/monitoring/extension.go b/pkg/extensions/monitoring/extension.go index e9c8eacf..50c32097 100644 --- a/pkg/extensions/monitoring/extension.go +++ b/pkg/extensions/monitoring/extension.go @@ -220,8 +220,8 @@ func IncDownloadCounter(ms MetricServer, repo string) { func SetStorageUsage(ms MetricServer, rootDir, repo string) { ms.ForceSendMetric(func() { dir := path.Join(rootDir, repo) - repoSize, err := GetDirSize(dir) + repoSize, err := GetDirSize(dir) if err == nil { repoStorageBytes.WithLabelValues(repo).Set(float64(repoSize)) } diff --git a/pkg/extensions/monitoring/minimal.go b/pkg/extensions/monitoring/minimal.go index 6a7fe8e5..7b617b88 100644 --- a/pkg/extensions/monitoring/minimal.go +++ b/pkg/extensions/monitoring/minimal.go @@ -439,6 +439,7 @@ func (ms *metricServer) HistogramObserve(hv *HistogramValue) { cachedH := ms.cache.Histograms[index] cachedH.Count++ cachedH.Sum += hv.Sum + for _, fvalue := range GetBuckets(hv.Name) { if hv.Sum <= fvalue { cachedH.Buckets[ms.bucketsF2S[fvalue]]++ @@ -478,6 +479,7 @@ func IncHTTPConnRequests(ms MetricServer, lvs ...string) { func ObserveHTTPRepoLatency(ms MetricServer, path string, latency time.Duration) { var lvs []string + match := re.FindStringSubmatch(path) if len(match) > 1 { diff --git a/pkg/extensions/monitoring/monitoring_test.go b/pkg/extensions/monitoring/monitoring_test.go index fad46c8a..64469834 100644 --- a/pkg/extensions/monitoring/monitoring_test.go +++ b/pkg/extensions/monitoring/monitoring_test.go @@ -90,9 +90,10 @@ func TestExtensionMetrics(t *testing.T) { conf := config.New() conf.HTTP.Port = port + var disabled bool + conf.Storage.RootDirectory = t.TempDir() conf.Extensions = &extconf.ExtensionConfig{} - var disabled bool conf.Extensions.Metrics = &extconf.MetricsConfig{BaseConfig: extconf.BaseConfig{Enable: &disabled}} ctlr := api.NewController(conf) @@ -169,6 +170,7 @@ func TestMetricsAuthentication(t *testing.T) { metricsuser := generateRandomString() metricspass := generateRandomString() content := test.GetCredString(username, password) + "\n" + test.GetCredString(metricsuser, metricspass) + htpasswdPath := test.MakeHtpasswdFileFromString(content) defer os.Remove(htpasswdPath) @@ -233,6 +235,7 @@ func TestMetricsAuthorization(t *testing.T) { metricsuser := generateRandomString() metricspass := generateRandomString() content := test.GetCredString(username, password) + "\n" + test.GetCredString(metricsuser, metricspass) + htpasswdPath := test.MakeHtpasswdFileFromString(content) defer os.Remove(htpasswdPath) diff --git a/pkg/extensions/scrub/scrub.go b/pkg/extensions/scrub/scrub.go index 8f4d07df..58bfcdc5 100644 --- a/pkg/extensions/scrub/scrub.go +++ b/pkg/extensions/scrub/scrub.go @@ -15,14 +15,14 @@ import ( // Scrub Extension for repo... func RunScrubRepo(ctx context.Context, imgStore storageTypes.ImageStore, repo string, log log.Logger) error { - execMsg := fmt.Sprintf("executing scrub to check manifest/blob integrity for %s", path.Join(imgStore.RootDir(), repo)) + execMsg := "executing scrub to check manifest/blob integrity for " + path.Join(imgStore.RootDir(), repo) log.Info().Msg(execMsg) results, err := storage.CheckRepo(ctx, repo, imgStore) if err != nil { - errMessage := fmt.Sprintf("failed to run scrub for %s", path.Join(imgStore.RootDir(), repo)) + errMessage := "failed to run scrub for " + path.Join(imgStore.RootDir(), repo) log.Error().Err(err).Msg(errMessage) - log.Info().Msg(fmt.Sprintf("scrub unsuccessfully completed for %s", path.Join(imgStore.RootDir(), repo))) + log.Info().Msg("scrub unsuccessfully completed for " + path.Join(imgStore.RootDir(), repo)) return err } @@ -47,7 +47,7 @@ func RunScrubRepo(ctx context.Context, imgStore storageTypes.ImageStore, repo st } } - log.Info().Msg(fmt.Sprintf("scrub successfully completed for %s", path.Join(imgStore.RootDir(), repo))) + log.Info().Msg("scrub successfully completed for " + path.Join(imgStore.RootDir(), repo)) return nil } diff --git a/pkg/extensions/scrub/scrub_test.go b/pkg/extensions/scrub/scrub_test.go index eb4f3c72..3406ea50 100644 --- a/pkg/extensions/scrub/scrub_test.go +++ b/pkg/extensions/scrub/scrub_test.go @@ -5,7 +5,6 @@ package scrub_test import ( "context" - "fmt" "os" "path" "testing" @@ -289,7 +288,7 @@ func TestRunScrubRepo(t *testing.T) { data, err := os.ReadFile(logFile.Name()) So(err, ShouldBeNil) So(string(data), ShouldContainSubstring, - fmt.Sprintf("failed to run scrub for %s", imgStore.RootDir())) + "failed to run scrub for "+imgStore.RootDir()) So(os.Chmod(path.Join(dir, repoName), 0o755), ShouldBeNil) }) } diff --git a/pkg/extensions/search/convert/convert_internal_test.go b/pkg/extensions/search/convert/convert_internal_test.go index 9b54b8bb..6a265cf4 100644 --- a/pkg/extensions/search/convert/convert_internal_test.go +++ b/pkg/extensions/search/convert/convert_internal_test.go @@ -161,6 +161,7 @@ func TestCVEConvert(t *testing.T) { Convey("Add CVE Summary to RepoSummary", func() { var repoSummary *gql_generated.RepoSummary + So(repoSummary, ShouldBeNil) updateRepoSummaryVulnerabilities(ctx, diff --git a/pkg/extensions/search/cve/cve.go b/pkg/extensions/search/cve/cve.go index 1ebf530e..7a7c0bfa 100644 --- a/pkg/extensions/search/cve/cve.go +++ b/pkg/extensions/search/cve/cve.go @@ -212,12 +212,14 @@ func (cveinfo BaseCveInfo) GetImageListWithCVEFixed(ctx context.Context, repo, c if len(vulnerableTags) != 0 { cveinfo.Log.Info().Str("repository", repo).Str("cve-id", cveID). Interface("tags", vulnerableTags).Msg("vulnerable tags") + fixedTags = GetFixedTags(allTags, vulnerableTags) cveinfo.Log.Info().Str("repository", repo).Str("cve-id", cveID). Interface("tags", fixedTags).Msg("fixed tags") } else { cveinfo.Log.Info().Str("repository", repo).Str("cve-id", cveID). Msg("image does not contain any tag that have given cve") + fixedTags = allTags } diff --git a/pkg/extensions/search/cve/cve_test.go b/pkg/extensions/search/cve/cve_test.go index 8eee4953..cd5f9096 100644 --- a/pkg/extensions/search/cve/cve_test.go +++ b/pkg/extensions/search/cve/cve_test.go @@ -157,16 +157,14 @@ func generateTestData(dbDir string) error { //nolint: gocyclo return err } - content = fmt.Sprint(`{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:2a9b097b4e4c613dd8185eba55163201a221909f3d430f8df87cd3639afc5929","size":1240,"annotations":{"org.opencontainers.image.ref.name":"commit-aaa7c6e7-squashfs"},"platform":{"architecture":"amd64","os":"linux"}}]} - `) + content = `{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:2a9b097b4e4c613dd8185eba55163201a221909f3d430f8df87cd3639afc5929","size":1240,"annotations":{"org.opencontainers.image.ref.name":"commit-aaa7c6e7-squashfs"},"platform":{"architecture":"amd64","os":"linux"}}]}` err = makeTestFile(path.Join(dbDir, "zot-squashfs-invalid-blob", "index.json"), content) if err != nil { return err } - content = fmt.Sprint(`{"schemaVersion":2,"config"{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:4b37d4133908ac9a3032ba996020f2ad41354a616b071ca7e726a1df18a0f354","size":1691},"layers":[{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:a01a66356aace53222e92fb6fd990b23eb44ab0e58dff6f853fa9f771ecf3ac5","size":54996992},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:91c26d6934ef2b5c5c4d8458af9bfc4ca46cf90c22380193154964abc8298a7a","size":52330496},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:f281a550ca49746cfc6b8f1ac52f8086b3d5845db2ca18fde980dab62ae3bf7d","size":23343104},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:7ee02568717acdda336c9d56d4dc6ea7f3b1c553e43bb0c0ecc6fd3bbd059d1a","size":5910528},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:8fb33b130588b239235dedd560cdf49d29bbf6f2db5419ac68e4592a85c1f416","size":123269120},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:1b49f0b33d4a696bb94d84c9acab3623e2c195bfb446d446a583a2f9f27b04c3","size":113901568}],"annotations":{"com.cisco.stacker.git_version":"7-dev19-63-gaaa7c6e7","ws.tycho.stacker.git_version":"0.3.26"}} - `) + content = `{"schemaVersion":2,"config"{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:4b37d4133908ac9a3032ba996020f2ad41354a616b071ca7e726a1df18a0f354","size":1691},"layers":[{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:a01a66356aace53222e92fb6fd990b23eb44ab0e58dff6f853fa9f771ecf3ac5","size":54996992},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:91c26d6934ef2b5c5c4d8458af9bfc4ca46cf90c22380193154964abc8298a7a","size":52330496},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:f281a550ca49746cfc6b8f1ac52f8086b3d5845db2ca18fde980dab62ae3bf7d","size":23343104},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:7ee02568717acdda336c9d56d4dc6ea7f3b1c553e43bb0c0ecc6fd3bbd059d1a","size":5910528},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:8fb33b130588b239235dedd560cdf49d29bbf6f2db5419ac68e4592a85c1f416","size":123269120},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:1b49f0b33d4a696bb94d84c9acab3623e2c195bfb446d446a583a2f9f27b04c3","size":113901568}],"annotations":{"com.cisco.stacker.git_version":"7-dev19-63-gaaa7c6e7","ws.tycho.stacker.git_version":"0.3.26"}}` err = makeTestFile(path.Join(dbDir, "zot-squashfs-invalid-blob", "blobs/sha256", "2a9b097b4e4c613dd8185eba55163201a221909f3d430f8df87cd3639afc5929"), content) if err != nil { @@ -181,8 +179,8 @@ func generateTestData(dbDir string) error { //nolint: gocyclo } il := ispec.ImageLayout{Version: ispec.ImageLayoutVersion} - buf, err = json.Marshal(il) + buf, err = json.Marshal(il) if err != nil { return err } @@ -196,49 +194,51 @@ func generateTestData(dbDir string) error { //nolint: gocyclo return err } - content = fmt.Sprint(`{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:eca04f027f414362596f2632746d8a178362170b9ac9af772011fedcc3877ebb","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.25"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:45df53588e59759a12bd3eca553cdc9063939baac9a28d7ebb6101e4ec230b76","size":873,"annotations":{"org.opencontainers.image.ref.name":"0.3.22-squashfs"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:71448405a4b89539fcfa581afb4dc7d257f98857686b8138b08a1c539f313099","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.19"},"platform":{"architecture":"amd64","os":"linux"}}]}`) + //nolint:goconst + content = `{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:eca04f027f414362596f2632746d8a178362170b9ac9af772011fedcc3877ebb","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.25"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:45df53588e59759a12bd3eca553cdc9063939baac9a28d7ebb6101e4ec230b76","size":873,"annotations":{"org.opencontainers.image.ref.name":"0.3.22-squashfs"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:71448405a4b89539fcfa581afb4dc7d257f98857686b8138b08a1c539f313099","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.19"},"platform":{"architecture":"amd64","os":"linux"}}]}` err = makeTestFile(path.Join(dbDir, "zot-squashfs-test", "index.json"), content) if err != nil { return err } - content = fmt.Sprint(`{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:c5c2fd2b07ad4cb025cf20936d6bce6085584b8377780599be4da8a91739f0e8","size":1738},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:3414b5ef0ad2f0390daaf55b63c422eeedef6191d47036a69d8ee396fabdce72","size":58993484},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:a3b04fff744c13dfa4883e01fa35e01af8daa7f72d9e9b6b7fad1f28843846b6","size":55631733},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:754f517f58f302190aa94e025c25890c18e1e811127aed1ef25c189278ec4ab0","size":113612795},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:ec004cd43488b803d6e232599e83a3164394d44fcd9f44755fed7b5791087ede","size":108889651}],"annotations":{"ws.tycho.stacker.git_version":"0.3.19"}}`) + content = `{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:c5c2fd2b07ad4cb025cf20936d6bce6085584b8377780599be4da8a91739f0e8","size":1738},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:3414b5ef0ad2f0390daaf55b63c422eeedef6191d47036a69d8ee396fabdce72","size":58993484},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:a3b04fff744c13dfa4883e01fa35e01af8daa7f72d9e9b6b7fad1f28843846b6","size":55631733},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:754f517f58f302190aa94e025c25890c18e1e811127aed1ef25c189278ec4ab0","size":113612795},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:ec004cd43488b803d6e232599e83a3164394d44fcd9f44755fed7b5791087ede","size":108889651}],"annotations":{"ws.tycho.stacker.git_version":"0.3.19"}}` err = makeTestFile(path.Join(dbDir, "zot-squashfs-test", "blobs/sha256", "71448405a4b89539fcfa581afb4dc7d257f98857686b8138b08a1c539f313099"), content) if err != nil { return err } - content = fmt.Sprint(`{"created": "2020-04-08T05:32:49.805795564Z","author": "","architecture": "amd64","os": "linux","config": {"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"rootfs": {"type": "layers","diff_ids": []},"history": [{"created": "2020-04-08T05:08:43.590117872Z","created_by": "stacker umoci repack"}, {"created": "2020-04-08T05:08:53.213437118Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:12:15.999154739Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:12:31.0513552Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:20:38.068800557Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:21:01.956154957Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:32:24.582132274Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:32:49.805795564Z","created_by": "stacker build","author": "","empty_layer": true}]}`) + content = `{"created": "2020-04-08T05:32:49.805795564Z","author": "","architecture": "amd64","os": "linux","config": {"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"rootfs": {"type": "layers","diff_ids": []},"history": [{"created": "2020-04-08T05:08:43.590117872Z","created_by": "stacker umoci repack"}, {"created": "2020-04-08T05:08:53.213437118Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:12:15.999154739Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:12:31.0513552Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:20:38.068800557Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:21:01.956154957Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:32:24.582132274Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:32:49.805795564Z","created_by": "stacker build","author": "","empty_layer": true}]}` err = makeTestFile(path.Join(dbDir, "zot-squashfs-test", "blobs/sha256", "c5c2fd2b07ad4cb025cf20936d6bce6085584b8377780599be4da8a91739f0e8"), content) if err != nil { return err } - content = fmt.Sprint(`{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:5f00b5570a5561a6f9b7e66e4f26e2e30c4d09b43a8d3f993f3c1c99be6137a6","size":1740},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:f8b7e41ce10d9a0f614f068326c43431c2777e6fc346f729c2a643bfab24af83","size":59451113},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:9ca9274f196b56a708a7a672d3de88184c0158a30744d355dd0411f3a6850fa6","size":55685756},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:6c1ca50788f93937e9ce9341b564f86cbbcd28e367ed6a57cfc776aee4a9d050","size":113726186},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:d1a92139df86bdf00c818db75bf1ecc860857d142b426e9971a62f5f90e2aa57","size":108755643}],"annotations":{"ws.tycho.stacker.git_version":"0.3.25"}}`) + //nolint:goconst + content = `{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:5f00b5570a5561a6f9b7e66e4f26e2e30c4d09b43a8d3f993f3c1c99be6137a6","size":1740},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:f8b7e41ce10d9a0f614f068326c43431c2777e6fc346f729c2a643bfab24af83","size":59451113},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:9ca9274f196b56a708a7a672d3de88184c0158a30744d355dd0411f3a6850fa6","size":55685756},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:6c1ca50788f93937e9ce9341b564f86cbbcd28e367ed6a57cfc776aee4a9d050","size":113726186},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:d1a92139df86bdf00c818db75bf1ecc860857d142b426e9971a62f5f90e2aa57","size":108755643}],"annotations":{"ws.tycho.stacker.git_version":"0.3.25"}}` err = makeTestFile(path.Join(dbDir, "zot-squashfs-test", "blobs/sha256", "eca04f027f414362596f2632746d8a178362170b9ac9af772011fedcc3877ebb"), content) if err != nil { return err } - content = fmt.Sprint(`{"created": "2020-04-08T05:32:49.805795564Z","author": "","architecture": "amd64","os": "linux","config": {"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"rootfs": {"type": "layers","diff_ids": []},"history": [{"created": "2020-05-11T18:17:24.516727354Z","created_by": "stacker umoci repack"}, {"created": "2020-04-08T05:08:53.213437118Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:12:15.999154739Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:12:31.0513552Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:20:38.068800557Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:21:01.956154957Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:32:24.582132274Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:32:49.805795564Z","created_by": "stacker build","author": "","empty_layer": true}]}`) + content = `{"created": "2020-04-08T05:32:49.805795564Z","author": "","architecture": "amd64","os": "linux","config": {"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"rootfs": {"type": "layers","diff_ids": []},"history": [{"created": "2020-05-11T18:17:24.516727354Z","created_by": "stacker umoci repack"}, {"created": "2020-04-08T05:08:53.213437118Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:12:15.999154739Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:12:31.0513552Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:20:38.068800557Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:21:01.956154957Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:32:24.582132274Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:32:49.805795564Z","created_by": "stacker build","author": "","empty_layer": true}]}` err = makeTestFile(path.Join(dbDir, "zot-squashfs-test", "blobs/sha256", "5f00b5570a5561a6f9b7e66e4f26e2e30c4d09b43a8d3f993f3c1c99be6137a6"), content) if err != nil { return err } - content = fmt.Sprint(`{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:1fc1d045b241b04fea54333d76d4f57eb1961f9a314413f02a956b76e77a99f0","size":1218},"layers":[{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:c40d72b1556293c00a3e4b6c64c46ef4c7ae4d876dc18bad942b7d1903e8e5b7","size":54745420},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:4115890e3e2563e545e03f264bfecb0097e24e02306ae3e7668dea52e00c6cc2","size":52213357},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:91859e13e0cf704d5405199d73a2d1a0718391dbb183a77c4cb85d99e923ff57","size":109479329},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:20aef84d8098d47a0643a2f99ce05f0deed957b3a259fb708c538f23ed97cc82","size":103996238}],"annotations":{"ws.tycho.stacker.git_version":"0.3.25"}}`) + content = `{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:1fc1d045b241b04fea54333d76d4f57eb1961f9a314413f02a956b76e77a99f0","size":1218},"layers":[{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:c40d72b1556293c00a3e4b6c64c46ef4c7ae4d876dc18bad942b7d1903e8e5b7","size":54745420},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:4115890e3e2563e545e03f264bfecb0097e24e02306ae3e7668dea52e00c6cc2","size":52213357},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:91859e13e0cf704d5405199d73a2d1a0718391dbb183a77c4cb85d99e923ff57","size":109479329},{"mediaType":"application/vnd.oci.image.layer.squashfs","digest":"sha256:20aef84d8098d47a0643a2f99ce05f0deed957b3a259fb708c538f23ed97cc82","size":103996238}],"annotations":{"ws.tycho.stacker.git_version":"0.3.25"}}` err = makeTestFile(path.Join(dbDir, "zot-squashfs-test", "blobs/sha256", "45df53588e59759a12bd3eca553cdc9063939baac9a28d7ebb6101e4ec230b76"), content) if err != nil { return err } - content = fmt.Sprint(`{"created": "2020-04-08T05:32:49.805795564Z","author": "","architecture": "amd64","os": "linux","config": {"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"rootfs": {"type": "layers","diff_ids": []},"history": [{"created": "2020-05-11T18:17:24.516727354Z","created_by": "stacker umoci repack"}, {"created": "2020-04-08T05:08:53.213437118Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:12:15.999154739Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-05-11T19:30:02.467956112Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:20:38.068800557Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:21:01.956154957Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:32:24.582132274Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:32:49.805795564Z","created_by": "stacker build","author": "","empty_layer": true}]}`) + content = `{"created": "2020-04-08T05:32:49.805795564Z","author": "","architecture": "amd64","os": "linux","config": {"Env": ["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"rootfs": {"type": "layers","diff_ids": []},"history": [{"created": "2020-05-11T18:17:24.516727354Z","created_by": "stacker umoci repack"}, {"created": "2020-04-08T05:08:53.213437118Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:12:15.999154739Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-05-11T19:30:02.467956112Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:20:38.068800557Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:21:01.956154957Z","created_by": "stacker build","author": "","empty_layer": true}, {"created": "2020-04-08T05:32:24.582132274Z","created_by": "stacker umoci repack","author": ""}, {"created": "2020-04-08T05:32:49.805795564Z","created_by": "stacker build","author": "","empty_layer": true}]}` err = makeTestFile(path.Join(dbDir, "zot-squashfs-test", "blobs/sha256", "1fc1d045b241b04fea54333d76d4f57eb1961f9a314413f02a956b76e77a99f0"), content) if err != nil { @@ -252,21 +252,21 @@ func generateTestData(dbDir string) error { //nolint: gocyclo return err } - content = fmt.Sprint(`{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:eca04f027f414362596f2632746d8a178362170b9ac9af772011fedcc3877ebb","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.25"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:45df53588e59759a12bd3eca553cdc9063939baac9a28d7ebb6101e4ec230b76","size":873,"annotations":{"org.opencontainers.image.ref.name":"0.3.22-squashfs"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:71448405a4b89539fcfa581afb4dc7d257f98857686b8138b08a1c539f313099","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.19"},"platform":{"architecture":"amd64","os":"linux"}}]}`) + content = `{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:eca04f027f414362596f2632746d8a178362170b9ac9af772011fedcc3877ebb","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.25"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:45df53588e59759a12bd3eca553cdc9063939baac9a28d7ebb6101e4ec230b76","size":873,"annotations":{"org.opencontainers.image.ref.name":"0.3.22-squashfs"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:71448405a4b89539fcfa581afb4dc7d257f98857686b8138b08a1c539f313099","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.19"},"platform":{"architecture":"amd64","os":"linux"}}]}` err = makeTestFile(path.Join(dbDir, "zot-invalid-layer", "index.json"), content) if err != nil { return err } - content = fmt.Sprint(`{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:5f00b5570a5561a6f9b7e66e4f26e2e30c4d09b43a8d3f993f3c1c99be6137a6","size":1740},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:f8b7e41ce10d9a0f614f068326c43431c2777e6fc346f729c2a643bfab24af83","size":59451113},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:9ca9274f196b56a708a7a672d3de88184c0158a30744d355dd0411f3a6850fa6","size":55685756},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:6c1ca50788f93937e9ce9341b564f86cbbcd28e367ed6a57cfc776aee4a9d050","size":113726186},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:d1a92139df86bdf00c818db75bf1ecc860857d142b426e9971a62f5f90e2aa57","size":108755643}],"annotations":{"ws.tycho.stacker.git_version":"0.3.25"}}`) + content = `{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:5f00b5570a5561a6f9b7e66e4f26e2e30c4d09b43a8d3f993f3c1c99be6137a6","size":1740},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:f8b7e41ce10d9a0f614f068326c43431c2777e6fc346f729c2a643bfab24af83","size":59451113},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:9ca9274f196b56a708a7a672d3de88184c0158a30744d355dd0411f3a6850fa6","size":55685756},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:6c1ca50788f93937e9ce9341b564f86cbbcd28e367ed6a57cfc776aee4a9d050","size":113726186},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:d1a92139df86bdf00c818db75bf1ecc860857d142b426e9971a62f5f90e2aa57","size":108755643}],"annotations":{"ws.tycho.stacker.git_version":"0.3.25"}}` err = makeTestFile(path.Join(dbDir, "zot-invalid-layer", "blobs/sha256", "eca04f027f414362596f2632746d8a178362170b9ac9af772011fedcc3877ebb"), content) if err != nil { return err } - content = fmt.Sprint(`{"created":"2020-05-11T19:12:23.239785708Z","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","architecture":"amd64","os":"linux","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"rootfs":{"type":"layers","diff_ids":["sha256:8817d297aa60796f41f559ba688d29b31830854014091233575d474f3a6e808e","sha256:dd5a09481ae1f5caf8d1dbc87bc7f86a01af030796467ba25851ad69964d226d","sha256:a8bce2aaf5ce6f1a5459b72de64927a1e507a911453789bf60df06752222cacd","sha256:dc0b750a934e8f376af23de6dcab1af282967498844a6510aed2c61277f20c11"]},"history":[{"created":"2020-05-11T18:17:24.516727354Z","created_by":"stacker umoci repack"},{"created":"2020-05-11T18:17:33.111086359Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T18:18:43.147035914Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T18:19:03.346279546Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T18:27:01.623678656Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T18:27:23.420280147Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T19:11:54.886053615Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T19:12:23.239785708Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true}]`) + content = `{"created":"2020-05-11T19:12:23.239785708Z","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","architecture":"amd64","os":"linux","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"rootfs":{"type":"layers","diff_ids":["sha256:8817d297aa60796f41f559ba688d29b31830854014091233575d474f3a6e808e","sha256:dd5a09481ae1f5caf8d1dbc87bc7f86a01af030796467ba25851ad69964d226d","sha256:a8bce2aaf5ce6f1a5459b72de64927a1e507a911453789bf60df06752222cacd","sha256:dc0b750a934e8f376af23de6dcab1af282967498844a6510aed2c61277f20c11"]},"history":[{"created":"2020-05-11T18:17:24.516727354Z","created_by":"stacker umoci repack"},{"created":"2020-05-11T18:17:33.111086359Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T18:18:43.147035914Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T18:19:03.346279546Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T18:27:01.623678656Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T18:27:23.420280147Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T19:11:54.886053615Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T19:12:23.239785708Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true}]` err = makeTestFile(path.Join(dbDir, "zot-invalid-layer", "blobs/sha256", "5f00b5570a5561a6f9b7e66e4f26e2e30c4d09b43a8d3f993f3c1c99be6137a6"), content) if err != nil { @@ -280,21 +280,21 @@ func generateTestData(dbDir string) error { //nolint: gocyclo return err } - content = fmt.Sprint(`{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:eca04f027f414362596f2632746d8a178362170b9ac9af772011fedcc3877ebb","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.25"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:45df53588e59759a12bd3eca553cdc9063939baac9a28d7ebb6101e4ec230b76","size":873,"annotations":{"org.opencontainers.image.ref.name":"0.3.22-squashfs"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:71448405a4b89539fcfa581afb4dc7d257f98857686b8138b08a1c539f313099","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.19"},"platform":{"architecture":"amd64","os":"linux"}}]}`) + content = `{"schemaVersion":2,"manifests":[{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:eca04f027f414362596f2632746d8a178362170b9ac9af772011fedcc3877ebb","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.25"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:45df53588e59759a12bd3eca553cdc9063939baac9a28d7ebb6101e4ec230b76","size":873,"annotations":{"org.opencontainers.image.ref.name":"0.3.22-squashfs"},"platform":{"architecture":"amd64","os":"linux"}},{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:71448405a4b89539fcfa581afb4dc7d257f98857686b8138b08a1c539f313099","size":886,"annotations":{"org.opencontainers.image.ref.name":"0.3.19"},"platform":{"architecture":"amd64","os":"linux"}}]}` err = makeTestFile(path.Join(dbDir, "zot-no-layer", "index.json"), content) if err != nil { return err } - content = fmt.Sprint(`{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:5f00b5570a5561a6f9b7e66e4f26e2e30c4d09b43a8d3f993f3c1c99be6137a6","size":1740},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:f8b7e41ce10d9a0f614f068326c43431c2777e6fc346f729c2a643bfab24af83","size":59451113},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:9ca9274f196b56a708a7a672d3de88184c0158a30744d355dd0411f3a6850fa6","size":55685756},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:6c1ca50788f93937e9ce9341b564f86cbbcd28e367ed6a57cfc776aee4a9d050","size":113726186},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:d1a92139df86bdf00c818db75bf1ecc860857d142b426e9971a62f5f90e2aa57","size":108755643}],"annotations":{"ws.tycho.stacker.git_version":"0.3.25"}}`) + content = `{"schemaVersion":2,"config":{"mediaType":"application/vnd.oci.image.config.v1+json","digest":"sha256:5f00b5570a5561a6f9b7e66e4f26e2e30c4d09b43a8d3f993f3c1c99be6137a6","size":1740},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:f8b7e41ce10d9a0f614f068326c43431c2777e6fc346f729c2a643bfab24af83","size":59451113},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:9ca9274f196b56a708a7a672d3de88184c0158a30744d355dd0411f3a6850fa6","size":55685756},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:6c1ca50788f93937e9ce9341b564f86cbbcd28e367ed6a57cfc776aee4a9d050","size":113726186},{"mediaType":"application/vnd.oci.image.layer.v1.tar+gzip","digest":"sha256:d1a92139df86bdf00c818db75bf1ecc860857d142b426e9971a62f5f90e2aa57","size":108755643}],"annotations":{"ws.tycho.stacker.git_version":"0.3.25"}}` err = makeTestFile(path.Join(dbDir, "zot-no-layer", "blobs/sha256", "eca04f027f414362596f2632746d8a178362170b9ac9af772011fedcc3877ebb"), content) if err != nil { return err } - content = fmt.Sprint(`{"created":"2020-05-11T19:12:23.239785708Z","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","architecture":"amd64","os":"linux","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"rootfs":{"type":"layers","diff_ids":["sha256:8817d297aa60796f41f559ba688d29b31830854014091233575d474f3a6e808e","sha256:dd5a09481ae1f5caf8d1dbc87bc7f86a01af030796467ba25851ad69964d226d","sha256:a8bce2aaf5ce6f1a5459b72de64927a1e507a911453789bf60df06752222cacd","sha256:dc0b750a934e8f376af23de6dcab1af282967498844a6510aed2c61277f20c11"]},"history":[{"created":"2020-05-11T18:17:24.516727354Z","created_by":"stacker umoci repack"},{"created":"2020-05-11T18:17:33.111086359Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T18:18:43.147035914Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T18:19:03.346279546Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T18:27:01.623678656Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T18:27:23.420280147Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T19:11:54.886053615Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T19:12:23.239785708Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true}]`) + content = `{"created":"2020-05-11T19:12:23.239785708Z","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","architecture":"amd64","os":"linux","config":{"Env":["PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"]},"rootfs":{"type":"layers","diff_ids":["sha256:8817d297aa60796f41f559ba688d29b31830854014091233575d474f3a6e808e","sha256:dd5a09481ae1f5caf8d1dbc87bc7f86a01af030796467ba25851ad69964d226d","sha256:a8bce2aaf5ce6f1a5459b72de64927a1e507a911453789bf60df06752222cacd","sha256:dc0b750a934e8f376af23de6dcab1af282967498844a6510aed2c61277f20c11"]},"history":[{"created":"2020-05-11T18:17:24.516727354Z","created_by":"stacker umoci repack"},{"created":"2020-05-11T18:17:33.111086359Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T18:18:43.147035914Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T18:19:03.346279546Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T18:27:01.623678656Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T18:27:23.420280147Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true},{"created":"2020-05-11T19:11:54.886053615Z","created_by":"stacker umoci repack","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI"},{"created":"2020-05-11T19:12:23.239785708Z","created_by":"stacker build","author":"root@jenkinsProduction-Atom-Full-Build-c3-master-159CI","empty_layer":true}]` err = makeTestFile(path.Join(dbDir, "zot-no-layer", "blobs/sha256", "5f00b5570a5561a6f9b7e66e4f26e2e30c4d09b43a8d3f993f3c1c99be6137a"), content) if err != nil { @@ -423,6 +423,7 @@ func TestCVESearchDisabled(t *testing.T) { conf.HTTP.Port = port username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) defer os.Remove(htpasswdPath) @@ -491,6 +492,7 @@ func TestCVESearch(t *testing.T) { conf.HTTP.Port = port username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) defer os.Remove(htpasswdPath) @@ -560,15 +562,17 @@ func TestCVESearch(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 401) - var apiErr apiErr.Error - err = json.Unmarshal(resp.Body(), &apiErr) + + var apiError apiErr.Error + + err = json.Unmarshal(resp.Body(), &apiError) So(err, ShouldBeNil) resp, err = resty.R().Get(baseURL + constants.FullSearchPrefix) So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, 401) - err = json.Unmarshal(resp.Body(), &apiErr) + err = json.Unmarshal(resp.Body(), &apiError) So(err, ShouldBeNil) // with creds, should get expected status code @@ -587,14 +591,17 @@ func TestCVESearch(t *testing.T) { var cveResult CveResult contains := false resp, _ = resty.R().SetBasicAuth(username, password).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") + err = json.Unmarshal(resp.Body(), &cveResult) So(err, ShouldBeNil) + for _, err := range cveResult.Errors { result := strings.Contains(err.Message, "no reference provided") if result { contains = result } } + So(contains, ShouldBeTrue) resp, _ = resty.R().SetBasicAuth(username, password).Get(baseURL + constants.FullSearchPrefix + "?query={CVEListForImage(image:\"zot-test:0.0.1\"){Tag%20CVEList{Id%20Description%20Severity%20PackageList{Name%20InstalledVersion%20FixedVersion}}}}") @@ -746,16 +753,18 @@ func TestCVESearch(t *testing.T) { func TestCVEStruct(t *testing.T) { //nolint:gocyclo Convey("Unit test the CVE struct", t, func() { - const repo1 = "repo1" - const repo2 = "repo2" - const repo3 = "repo3" - const repo4 = "repo4" - const repo5 = "repo5" - const repo6 = "repo6" - const repo7 = "repo7" - const repo8 = "repo8" - const repo100 = "repo100" - const repoMultiarch = "repoIndex" + const ( + repo1 = "repo1" + repo2 = "repo2" + repo3 = "repo3" + repo4 = "repo4" + repo5 = "repo5" + repo6 = "repo6" + repo7 = "repo7" + repo8 = "repo8" + repo100 = "repo100" + repoMultiarch = "repoIndex" + ) params := boltdb.DBParameters{ RootDir: t.TempDir(), diff --git a/pkg/extensions/search/cve/pagination_test.go b/pkg/extensions/search/cve/pagination_test.go index 53a43e29..99607437 100644 --- a/pkg/extensions/search/cve/pagination_test.go +++ b/pkg/extensions/search/cve/pagination_test.go @@ -154,6 +154,7 @@ func TestCVEPagination(t *testing.T) { So(cveSummary.CriticalCount, ShouldEqual, 1) So(cveSummary.MaxSeverity, ShouldEqual, "CRITICAL") previousSeverity := 4 + for _, cve := range cves { So(severityToInt[cve.Severity], ShouldBeLessThanOrEqualTo, previousSeverity) previousSeverity = severityToInt[cve.Severity] @@ -173,6 +174,7 @@ func TestCVEPagination(t *testing.T) { So(cveSummary.CriticalCount, ShouldEqual, 6) So(cveSummary.MaxSeverity, ShouldEqual, "CRITICAL") previousSeverity = 4 + for _, cve := range cves { So(severityToInt[cve.Severity], ShouldBeLessThanOrEqualTo, previousSeverity) previousSeverity = severityToInt[cve.Severity] @@ -198,6 +200,7 @@ func TestCVEPagination(t *testing.T) { So(cveSummary.HighCount, ShouldEqual, 1) So(cveSummary.CriticalCount, ShouldEqual, 1) So(cveSummary.MaxSeverity, ShouldEqual, "CRITICAL") + for i, cve := range cves { So(cve.ID, ShouldEqual, cveIds[i]) } @@ -216,6 +219,7 @@ func TestCVEPagination(t *testing.T) { So(cveSummary.HighCount, ShouldEqual, 6) So(cveSummary.CriticalCount, ShouldEqual, 6) So(cveSummary.MaxSeverity, ShouldEqual, "CRITICAL") + for i, cve := range cves { So(cve.ID, ShouldEqual, cveIds[i]) } @@ -234,6 +238,7 @@ func TestCVEPagination(t *testing.T) { So(cveSummary.HighCount, ShouldEqual, 6) So(cveSummary.CriticalCount, ShouldEqual, 6) So(cveSummary.MaxSeverity, ShouldEqual, "CRITICAL") + for i, cve := range cves { So(cve.ID, ShouldEqual, cveIds[i]) } @@ -252,6 +257,7 @@ func TestCVEPagination(t *testing.T) { So(cveSummary.CriticalCount, ShouldEqual, 6) So(cveSummary.MaxSeverity, ShouldEqual, "CRITICAL") previousSeverity := 4 + for _, cve := range cves { So(severityToInt[cve.Severity], ShouldBeLessThanOrEqualTo, previousSeverity) previousSeverity = severityToInt[cve.Severity] @@ -323,6 +329,7 @@ func TestCVEPagination(t *testing.T) { So(cveSummary.CriticalCount, ShouldEqual, 1) So(cveSummary.MaxSeverity, ShouldEqual, "CRITICAL") previousSeverity := 4 + for _, cve := range cves { So(severityToInt[cve.Severity], ShouldBeLessThanOrEqualTo, previousSeverity) previousSeverity = severityToInt[cve.Severity] @@ -346,6 +353,7 @@ func TestCVEPagination(t *testing.T) { So(cveSummary.HighCount, ShouldEqual, 6) So(cveSummary.CriticalCount, ShouldEqual, 6) So(cveSummary.MaxSeverity, ShouldEqual, "CRITICAL") + for i, cve := range cves { So(cve.ID, ShouldEqual, cveIds[i+20]) } @@ -410,6 +418,7 @@ func TestCVEPagination(t *testing.T) { So(cveSummary.CriticalCount, ShouldEqual, 1) So(cveSummary.MaxSeverity, ShouldEqual, "CRITICAL") previousSeverity := 4 + for _, cve := range cves { So(severityToInt[cve.Severity], ShouldBeLessThanOrEqualTo, previousSeverity) previousSeverity = severityToInt[cve.Severity] diff --git a/pkg/extensions/search/cve/scan.go b/pkg/extensions/search/cve/scan.go index b84a4ada..a5344aea 100644 --- a/pkg/extensions/search/cve/scan.go +++ b/pkg/extensions/search/cve/scan.go @@ -142,7 +142,7 @@ func (gen *scanTaskGenerator) Next() (scheduler.Task, error) { gen.done = true - return nil, nil + return nil, nil //nolint:nilnil } // Since imageMeta will always contain just un-scanned images we can pick diff --git a/pkg/extensions/search/cve/scan_test.go b/pkg/extensions/search/cve/scan_test.go index bcc41978..363a2e7f 100644 --- a/pkg/extensions/search/cve/scan_test.go +++ b/pkg/extensions/search/cve/scan_test.go @@ -47,6 +47,7 @@ func TestScanGeneratorWithMockedData(t *testing.T) { //nolint: gocyclo logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt") logPath := logFile.Name() + So(err, ShouldBeNil) defer os.Remove(logFile.Name()) // clean up @@ -484,6 +485,7 @@ func TestScanGeneratorWithRealData(t *testing.T) { logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt") logPath := logFile.Name() + So(err, ShouldBeNil) defer os.Remove(logFile.Name()) // clean up diff --git a/pkg/extensions/search/cve/trivy/scanner.go b/pkg/extensions/search/cve/trivy/scanner.go index e04d076a..43bb085f 100644 --- a/pkg/extensions/search/cve/trivy/scanner.go +++ b/pkg/extensions/search/cve/trivy/scanner.go @@ -5,6 +5,7 @@ import ( "fmt" "os" "path" + "strconv" "strings" "sync" @@ -99,7 +100,7 @@ func NewScanner(storeController storage.StoreController, // Add the schema version if the tag is not specified for backward compatibility. if t, ok := dbRepositoryRef.(name.Tag); ok && t.TagStr() == "" { - dbRepositoryRef = t.Tag(fmt.Sprint(db.SchemaVersion)) + dbRepositoryRef = t.Tag(strconv.Itoa(db.SchemaVersion)) } var javaDBRepositoryRef name.Reference @@ -111,7 +112,7 @@ func NewScanner(storeController storage.StoreController, // Add the schema version if the tag is not specified for backward compatibility. if t, ok := javaDBRepositoryRef.(name.Tag); ok && t.TagStr() == "" { - javaDBRepositoryRef = t.Tag(fmt.Sprint(javadb.SchemaVersion)) + javaDBRepositoryRef = t.Tag(strconv.Itoa(javadb.SchemaVersion)) } } diff --git a/pkg/extensions/search/cve/update_test.go b/pkg/extensions/search/cve/update_test.go index cbb9a0e5..f1d34366 100644 --- a/pkg/extensions/search/cve/update_test.go +++ b/pkg/extensions/search/cve/update_test.go @@ -28,6 +28,7 @@ func TestCVEDBGenerator(t *testing.T) { Convey("Test CVE DB task scheduler reset", t, func() { logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt") logPath := logFile.Name() + So(err, ShouldBeNil) defer os.Remove(logFile.Name()) // clean up diff --git a/pkg/extensions/search/digest_test.go b/pkg/extensions/search/digest_test.go index 4731b2b2..4ba252cc 100644 --- a/pkg/extensions/search/digest_test.go +++ b/pkg/extensions/search/digest_test.go @@ -201,6 +201,7 @@ func TestDigestSearchHTTP(t *testing.T) { So(resp, ShouldNotBeNil) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, 200) + var responseStruct2 ImgResponseForDigest err = json.Unmarshal(resp.Body(), &responseStruct2) diff --git a/pkg/extensions/search/resolver.go b/pkg/extensions/search/resolver.go index 349932ae..3cd3f9ec 100644 --- a/pkg/extensions/search/resolver.go +++ b/pkg/extensions/search/resolver.go @@ -303,6 +303,7 @@ func getCVEDiffListForImages( if err != nil { return nil, err } + resultSubtrahend = getImageIdentifier(subtrahend) } else { // search for base images @@ -1124,6 +1125,7 @@ func filterDerivedImages(image *gql_generated.ImageSummary) mTypes.FilterFunc { if manifestDigest == *image.Manifests[i].Digest { return false } + imageLayers := image.Manifests[i].Layers addImageToList = false diff --git a/pkg/extensions/search/resolver_test.go b/pkg/extensions/search/resolver_test.go index 16651604..bfc17e76 100644 --- a/pkg/extensions/search/resolver_test.go +++ b/pkg/extensions/search/resolver_test.go @@ -36,6 +36,7 @@ var ErrTestError = errors.New("TestError") func TestResolverGlobalSearch(t *testing.T) { Convey("globalSearch", t, func() { const query = "repo1" + Convey("MetaDB SearchRepos error", func() { mockMetaDB := mocks.MetaDBMock{ SearchReposFn: func(ctx context.Context, searchText string, @@ -77,6 +78,7 @@ func TestResolverGlobalSearch(t *testing.T) { return []mTypes.FullImageMeta{}, ErrTestError }, } + const query = "repo1:1.0.1" mockCve := mocks.CveInfoMock{} @@ -292,6 +294,7 @@ func TestRepoListWithNewestImage(t *testing.T) { }, nil }, } + Convey("MetaDB missing requestedPage", func() { responseContext := graphql.WithResponseContext(context.Background(), graphql.DefaultErrorPresenter, graphql.DefaultRecover) @@ -560,6 +563,7 @@ func TestGetImageSummaryError(t *testing.T) { func TestImageListError(t *testing.T) { Convey("getImageList", t, func() { testLogger := log.NewLogger("debug", "/dev/null") + Convey("no page requested, SearchRepoFn returns error", func() { mockMetaDB := mocks.MetaDBMock{ FilterTagsFn: func(ctx context.Context, filterRepoTag mTypes.FilterRepoTagFunc, filterFunc mTypes.FilterFunc, diff --git a/pkg/extensions/search/search_test.go b/pkg/extensions/search/search_test.go index 088ea839..9f2b2f13 100644 --- a/pkg/extensions/search/search_test.go +++ b/pkg/extensions/search/search_test.go @@ -681,6 +681,7 @@ func TestRepoListWithNewestImage(t *testing.T) { // stdout and a file logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt") So(err, ShouldBeNil) + logPath := logFile.Name() defer os.Remove(logPath) @@ -813,6 +814,7 @@ func TestGetReferrersGQL(t *testing.T) { ctlr := api.NewController(conf) ctlrManager := NewControllerManager(ctlr) ctlrManager.StartAndWait(port) + defer ctlrManager.StopServer() // ======================= @@ -937,6 +939,7 @@ func TestGetReferrersGQL(t *testing.T) { ctlr := api.NewController(conf) ctlrManager := NewControllerManager(ctlr) ctlrManager.StartAndWait(port) + defer ctlrManager.StopServer() // ======================= @@ -1061,6 +1064,7 @@ func TestGetReferrersGQL(t *testing.T) { conf.Extensions.Search.CVE = nil ctlr := api.NewController(conf) + ctlrManager := NewControllerManager(ctlr) ctlrManager.StartAndWait(port) defer ctlrManager.StopServer() @@ -1253,6 +1257,7 @@ func TestExpandedRepoInfo(t *testing.T) { ctlr := api.NewController(conf) ctlrManager := NewControllerManager(ctlr) ctlrManager.StartAndWait(port) + defer ctlrManager.StopServer() annotations := make(map[string]string) @@ -1336,12 +1341,15 @@ func TestExpandedRepoInfo(t *testing.T) { So(err, ShouldBeNil) found := false + for _, m := range responseStruct.ImageSummaries { if m.Manifests[0].Digest == testManifestDigest.String() { found = true + So(m.IsSigned, ShouldEqual, false) } } + So(found, ShouldEqual, true) err = signature.SignImageUsingCosign("zot-cve-test:0.0.1", port, false) @@ -1361,12 +1369,14 @@ func TestExpandedRepoInfo(t *testing.T) { So(err, ShouldBeNil) found = false + for _, m := range responseStruct.ImageSummaries { if m.Manifests[0].Digest == testManifestDigest.String() { found = true So(m.IsSigned, ShouldEqual, true) } } + So(found, ShouldEqual, true) query = `{ @@ -1408,12 +1418,15 @@ func TestExpandedRepoInfo(t *testing.T) { So(err, ShouldBeNil) found = false + for _, m := range responseStruct.ImageSummaries { if m.Manifests[0].Digest == testManifestDigest.String() { found = true + So(m.IsSigned, ShouldEqual, false) } } + So(found, ShouldEqual, true) err = signature.SignImageUsingCosign("zot-test@"+testManifestDigest.String(), port, false) @@ -1433,12 +1446,14 @@ func TestExpandedRepoInfo(t *testing.T) { So(err, ShouldBeNil) found = false + for _, m := range responseStruct.ImageSummaries { if m.Manifests[0].Digest == testManifestDigest.String() { found = true So(m.IsSigned, ShouldEqual, true) } } + So(found, ShouldEqual, true) manifestDigest := uploadedImage.ManifestDescriptor.Digest @@ -1474,6 +1489,7 @@ func TestExpandedRepoInfo(t *testing.T) { ctlr := api.NewController(conf) ctlrManager := NewControllerManager(ctlr) ctlrManager.StartAndWait(port) + defer ctlrManager.StopServer() image := CreateImageWith().RandomLayers(1, 20).DefaultConfig().Build() @@ -1709,6 +1725,7 @@ func TestExpandedRepoInfo(t *testing.T) { So(len(responseStruct.Summary.Platforms), ShouldNotEqual, 5) found := false + for _, is := range responseStruct.ImageSummaries { if is.Tag == "1.0.0" { found = true @@ -1716,9 +1733,11 @@ func TestExpandedRepoInfo(t *testing.T) { So(len(is.Manifests), ShouldEqual, 2) } } + So(found, ShouldBeTrue) found = false + for _, is := range responseStruct.ImageSummaries { if is.Tag == "2.0.0" { found = true @@ -1726,6 +1745,7 @@ func TestExpandedRepoInfo(t *testing.T) { So(len(is.Manifests), ShouldEqual, 3) } } + So(found, ShouldBeTrue) }) } @@ -2113,12 +2133,14 @@ func TestDerivedImageList(t *testing.T) { err = json.Unmarshal(resp.Body(), responseStruct) So(err, ShouldBeNil) + for _, err := range responseStruct.Errors { result := strings.Contains(err.Message, "no reference provided") if result { contains = result } } + So(contains, ShouldBeTrue) }) } @@ -2759,12 +2781,14 @@ func TestBaseImageList(t *testing.T) { err = json.Unmarshal(resp.Body(), responseStruct) So(err, ShouldBeNil) + for _, err := range responseStruct.Errors { result := strings.Contains(err.Message, "no reference provided") if result { contains = result } } + So(contains, ShouldBeTrue) }) } @@ -3132,10 +3156,12 @@ func TestGlobalSearch(t *testing.T) { allExpectedRepoInfoMap := make(map[string]zcommon.RepoInfo) allExpectedImageSummaryMap := make(map[string]zcommon.ImageSummary) + for _, repo := range repos { repoInfo, err := olu.GetExpandedRepoInfo(repo) So(err, ShouldBeNil) allExpectedRepoInfoMap[repo] = repoInfo + for _, image := range repoInfo.ImageSummaries { imageName := fmt.Sprintf("%s:%s", repo, image.Tag) allExpectedImageSummaryMap[imageName] = image @@ -3203,6 +3229,7 @@ func TestGlobalSearch(t *testing.T) { newestImageMap := make(map[string]zcommon.ImageSummary) actualRepoMap := make(map[string]zcommon.RepoSummary) + for _, repo := range responseStruct.Repos { newestImageMap[repo.Name] = repo.NewestImage actualRepoMap[repo.Name] = repo @@ -3350,6 +3377,7 @@ func TestGlobalSearch(t *testing.T) { // stdout and a file logFile, err := os.CreateTemp(t.TempDir(), "zot-log*.txt") So(err, ShouldBeNil) + logPath := logFile.Name() defer os.Remove(logPath) @@ -3477,10 +3505,12 @@ func TestGlobalSearch(t *testing.T) { allExpectedRepoInfoMap := make(map[string]zcommon.RepoInfo) allExpectedImageSummaryMap := make(map[string]zcommon.ImageSummary) + for _, repo := range repos { repoInfo, err := olu.GetExpandedRepoInfo(repo) So(err, ShouldBeNil) allExpectedRepoInfoMap[repo] = repoInfo + for _, image := range repoInfo.ImageSummaries { imageName := fmt.Sprintf("%s:%s", repo, image.Tag) allExpectedImageSummaryMap[imageName] = image @@ -3544,6 +3574,7 @@ func TestGlobalSearch(t *testing.T) { newestImageMap := make(map[string]zcommon.ImageSummary) actualRepoMap := make(map[string]zcommon.RepoSummary) + for _, repo := range responseStruct.Repos { newestImageMap[repo.Name] = repo.NewestImage actualRepoMap[repo.Name] = repo @@ -3572,6 +3603,7 @@ func TestGlobalSearch(t *testing.T) { // RepoInfo object does not provide vulnerability information so we need to check differently t.Logf("Found vulnerability summary %v", repoSummary.NewestImage.Vulnerabilities) + if repoName == "repo1" { //nolint:goconst So(repoSummary.NewestImage.Vulnerabilities.Count, ShouldEqual, 4) // There are 4 vulnerabilities in the data used in tests @@ -3800,6 +3832,7 @@ func TestGlobalSearch(t *testing.T) { So(len(results.Repos), ShouldEqual, 0) expectedRepos := []string{"repo1", "repo2", "repo3", "repo4", "repo5"} + for _, image := range results.Images { So(image.Tag, ShouldEqual, "tag1") So(image.RepoName, ShouldBeIn, expectedRepos) @@ -3812,6 +3845,7 @@ func TestGlobalSearch(t *testing.T) { So(len(results.Repos), ShouldEqual, 0) expectedRepos = []string{"repo2", "repo4"} + for _, image := range results.Images { So(image.Tag, ShouldEqual, "tag-multi") So(image.RepoName, ShouldBeIn, expectedRepos) @@ -3824,9 +3858,11 @@ func TestGlobalSearch(t *testing.T) { So(len(results.Repos), ShouldEqual, 0) expectedRepos = []string{"repo1", "repo2", "repo3", "repo4", "repo6"} + for _, image := range results.Images { So(image.Tag, ShouldEqual, "tag2") So(image.RepoName, ShouldBeIn, expectedRepos) + if image.RepoName == "repo6" { So(len(image.Manifests), ShouldEqual, 3) } else { @@ -3840,6 +3876,7 @@ func TestGlobalSearch(t *testing.T) { So(len(results.Repos), ShouldEqual, 0) expectedRepos = []string{"repo2", "repo4"} + for _, image := range results.Images { So(image.Tag, ShouldContainSubstring, "multi") So(image.RepoName, ShouldBeIn, expectedRepos) @@ -3852,6 +3889,7 @@ func TestGlobalSearch(t *testing.T) { So(len(results.Repos), ShouldEqual, 0) expectedRepos = []string{"repo1", "repo2", "repo3", "repo4", "repo5", "repo6"} + for _, image := range results.Images { So(image.Tag, ShouldContainSubstring, "tag") So(image.RepoName, ShouldBeIn, expectedRepos) @@ -4152,11 +4190,14 @@ func TestImageList(t *testing.T) { buf, _, _, err := imageStore.GetImageManifest(repos[0], tags[0]) So(err, ShouldBeNil) + var imageManifest ispec.Manifest + err = json.Unmarshal(buf, &imageManifest) So(err, ShouldBeNil) var imageConfigInfo ispec.Image + imageConfigBuf, err := imageStore.GetBlobContent(repos[0], imageManifest.Config.Digest) So(err, ShouldBeNil) err = json.Unmarshal(imageConfigBuf, &imageConfigInfo) @@ -4749,7 +4790,7 @@ func RunMetaDBIndexTests(baseURL, port string) { responseImage := responseImages[0] So(len(responseImage.Manifests), ShouldEqual, 3) - err = signature.SignImageUsingCosign(fmt.Sprintf("repo@%s", multiarchImage.DigestStr()), port, false) + err = signature.SignImageUsingCosign("repo@"+multiarchImage.DigestStr(), port, false) So(err, ShouldBeNil) resp, err = resty.R().Get(baseURL + graphqlQueryPrefix + "?query=" + url.QueryEscape(query)) @@ -5502,6 +5543,7 @@ func TestMetaDBWhenDeletingImages(t *testing.T) { for _, manifest := range indexContent.Manifests { manifestBlob, _, _, err := storage.GetImageManifest(repo, manifest.Digest.String()) So(err, ShouldBeNil) + var manifestContent ispec.Manifest err = json.Unmarshal(manifestBlob, &manifestContent) @@ -5520,7 +5562,9 @@ func TestMetaDBWhenDeletingImages(t *testing.T) { // check notation signature manifest1Blob, err := json.Marshal(image1.Manifest) So(err, ShouldBeNil) + manifest1Digest := godigest.FromBytes(manifest1Blob) + So(sigManifestContent.Subject, ShouldNotBeNil) So(sigManifestContent.Subject.Digest.String(), ShouldEqual, manifest1Digest.String()) @@ -5744,6 +5788,7 @@ func TestSearchSize(t *testing.T) { configSize := uploadedImage.ConfigDescriptor.Size manifestSize := uploadedImage.ManifestDescriptor.Size layersSize := int64(0) + for _, l := range uploadedImage.Layers { layersSize += int64(len(l)) } @@ -6025,6 +6070,7 @@ func TestImageSummary(t *testing.T) { contains := false resp, err = resty.R().Get(targetURL) + So(resp, ShouldNotBeNil) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, 200) @@ -6032,12 +6078,14 @@ func TestImageSummary(t *testing.T) { err = json.Unmarshal(resp.Body(), &imgSummaryResponse) So(err, ShouldBeNil) + for _, err := range imgSummaryResponse.Errors { result := strings.Contains(err.Message, "no reference provided") if result { contains = result } } + So(contains, ShouldBeTrue) t.Log("starting Test retrieve image based on image identifier") @@ -6214,6 +6262,7 @@ func TestImageSummary(t *testing.T) { tagTarget := "latest" err := UploadImage(image, baseURL, repoName, tagTarget) So(err, ShouldBeNil) + var ( imgSummaryResponse zcommon.ImageSummaryResult strQuery string diff --git a/pkg/extensions/search/userprefs_test.go b/pkg/extensions/search/userprefs_test.go index 9d6fab30..75c1d064 100644 --- a/pkg/extensions/search/userprefs_test.go +++ b/pkg/extensions/search/userprefs_test.go @@ -42,6 +42,7 @@ func TestUserData(t *testing.T) { content := test.GetCredString(adminUser, adminPassword) + test.GetCredString(simpleUser, simpleUserPassword) + htpasswdPath := test.MakeHtpasswdFileFromString(content) defer os.Remove(htpasswdPath) @@ -604,6 +605,7 @@ func TestGlobalSearchWithUserPrefFiltering(t *testing.T) { simpleUser := "simpleUser" simpleUserPassword := "simpleUserPass" + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(simpleUser, simpleUserPassword)) defer os.Remove(htpasswdPath) @@ -798,6 +800,7 @@ func TestExpandedRepoInfoWithUserPrefs(t *testing.T) { simpleUser := "simpleUser" simpleUserPassword := "simpleUserPass" + htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(simpleUser, simpleUserPassword)) defer os.Remove(htpasswdPath) diff --git a/pkg/extensions/sync/content_internal_test.go b/pkg/extensions/sync/content_internal_test.go index 118ee46c..78b03b6c 100644 --- a/pkg/extensions/sync/content_internal_test.go +++ b/pkg/extensions/sync/content_internal_test.go @@ -149,8 +149,10 @@ func TestGetContentByLocalRepo(t *testing.T) { for _, test := range testCases { cm := NewContentManager(test.content, log.Logger{}) actualResult := cm.getContentByLocalRepo(test.repo) + if test.expected == -1 { var tnil *syncconf.Content = nil + So(actualResult, ShouldEqual, tnil) } else { So(actualResult, ShouldEqual, &test.content[test.expected]) @@ -239,6 +241,7 @@ func TestFilterTags(t *testing.T) { cm := NewContentManager(test.content, log.NewLogger("debug", "")) actualResult, err := cm.FilterTags(test.repo, test.tags) So(actualResult, ShouldResemble, test.filteredTags) + if test.err { So(err, ShouldNotBeNil) } else { diff --git a/pkg/extensions/sync/destination.go b/pkg/extensions/sync/destination.go index 400a73a6..3384e627 100644 --- a/pkg/extensions/sync/destination.go +++ b/pkg/extensions/sync/destination.go @@ -295,7 +295,7 @@ func getTempRootDirFromImageReference(imageReference types.ImageReference, repo, if strings.HasSuffix(imageReference.StringWithinTransport(), reference) { tmpRootDir = strings.ReplaceAll(imageReference.StringWithinTransport(), fmt.Sprintf("%s:%s", repo, reference), "") } else { - tmpRootDir = strings.ReplaceAll(imageReference.StringWithinTransport(), fmt.Sprintf("%s:", repo), "") + tmpRootDir = strings.ReplaceAll(imageReference.StringWithinTransport(), repo+":", "") } return tmpRootDir diff --git a/pkg/extensions/sync/httpclient/client.go b/pkg/extensions/sync/httpclient/client.go index a2125dfe..ea248257 100644 --- a/pkg/extensions/sync/httpclient/client.go +++ b/pkg/extensions/sync/httpclient/client.go @@ -438,7 +438,7 @@ func parseAuthHeader(resp *http.Response) (challengeParams, error) { elem := strings.ReplaceAll(elem, "\"", "") elemSplit := strings.Split(elem, "=") - if len(elemSplit) != 2 { //nolint: gomnd + if len(elemSplit) != 2 { //nolint:mnd return params, zerr.ErrParsingAuthHeader } diff --git a/pkg/extensions/sync/references/cosign.go b/pkg/extensions/sync/references/cosign.go index bb62ad7f..eaa6008c 100644 --- a/pkg/extensions/sync/references/cosign.go +++ b/pkg/extensions/sync/references/cosign.go @@ -156,7 +156,6 @@ func (ref CosignReference) SyncReferences(ctx context.Context, localRepo, remote err = meta.SetImageMetaFromInput(ctx, localRepo, cosignTag, ispec.MediaTypeImageManifest, referenceDigest, manifestBuf, ref.storeController.GetImageStore(localRepo), ref.metaDB, ref.log) - if err != nil { return refsDigests, fmt.Errorf("failed to set metadata for cosign reference in '%s@%s': %w", localRepo, subjectDigestStr, err) diff --git a/pkg/extensions/sync/service.go b/pkg/extensions/sync/service.go index 75bf56f7..4f1fca23 100644 --- a/pkg/extensions/sync/service.go +++ b/pkg/extensions/sync/service.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + "strconv" "github.com/containers/common/pkg/retry" "github.com/containers/image/v5/copy" @@ -247,7 +248,7 @@ func (service *BaseService) GetNextRepo(lastRepo string) (string, error) { if targetIdx != service.clusterConfig.Proxy.LocalMemberClusterSocketIndex { service.log.Debug(). Str(constants.RepositoryLogKey, lastRepo). - Str("targetMemberIndex", fmt.Sprintf("%d", targetIdx)). + Str("targetMemberIndex", strconv.FormatUint(targetIdx, 10)). Str("targetMember", targetMember). Msg("skipping sync of repo not managed by local instance") diff --git a/pkg/extensions/sync/sync.go b/pkg/extensions/sync/sync.go index b0e67b25..1afd1117 100644 --- a/pkg/extensions/sync/sync.go +++ b/pkg/extensions/sync/sync.go @@ -114,7 +114,7 @@ func (gen *TaskGenerator) Next() (scheduler.Task, error) { defer gen.lock.Unlock() if time.Since(gen.lastTaskTime) <= gen.waitTime { - return nil, nil + return nil, nil //nolint:nilnil } if err := gen.Service.SetNextAvailableURL(); err != nil { @@ -136,7 +136,7 @@ func (gen *TaskGenerator) Next() (scheduler.Task, error) { gen.log.Info().Str("component", "sync").Msg("finished syncing all repositories") gen.done = true - return nil, nil + return nil, nil //nolint:nilnil } gen.lastRepo = repo diff --git a/pkg/extensions/sync/sync_internal_test.go b/pkg/extensions/sync/sync_internal_test.go index ed79e59e..5a03ae0f 100644 --- a/pkg/extensions/sync/sync_internal_test.go +++ b/pkg/extensions/sync/sync_internal_test.go @@ -7,6 +7,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "os" "path" @@ -45,7 +46,7 @@ const ( host = "127.0.0.1:45117" ) -var ErrTestError = fmt.Errorf("testError") +var ErrTestError = errors.New("testError") func TestInjectSyncUtils(t *testing.T) { Convey("Inject errors in utils functions", t, func() { @@ -62,6 +63,7 @@ func TestInjectSyncUtils(t *testing.T) { injected = inject.InjectFailure(0) _, err = getPolicyContext(log.NewLogger("debug", "")) + if injected { So(err, ShouldNotBeNil) } else { @@ -75,6 +77,7 @@ func TestInjectSyncUtils(t *testing.T) { ols := NewOciLayoutStorage(storage.StoreController{DefaultStore: imageStore}) _, err = ols.GetImageReference(testImage, testImageTag) + if injected { So(err, ShouldNotBeNil) } else { diff --git a/pkg/extensions/sync/sync_test.go b/pkg/extensions/sync/sync_test.go index 7bf98f2b..d0fc8a79 100644 --- a/pkg/extensions/sync/sync_test.go +++ b/pkg/extensions/sync/sync_test.go @@ -15,6 +15,7 @@ import ( "os" "path" "reflect" + "strconv" "strings" goSync "sync" "testing" @@ -267,6 +268,7 @@ func TestOnDemand(t *testing.T) { sctlr, srcBaseURL, _, _, srcClient := makeUpstreamServer(t, false, false) scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() var tlsVerify bool @@ -303,8 +305,10 @@ func TestOnDemand(t *testing.T) { dcm.StartAndWait(dctlr.Config.HTTP.Port) defer dcm.StopServer() - var srcTagsList TagsList - var destTagsList TagsList + var ( + srcTagsList TagsList + destTagsList TagsList + ) resp, _ := srcClient.R().Get(srcBaseURL + "/v2/" + testImage + "/tags/list") So(resp, ShouldNotBeNil) @@ -408,6 +412,7 @@ func TestOnDemand(t *testing.T) { sctlr, newSrcBaseURL, srcDir, _, srcClient := makeUpstreamServer(t, false, false) scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // remove remote testImage @@ -429,8 +434,10 @@ func TestOnDemand(t *testing.T) { dcm.StartAndWait(dctlr.Config.HTTP.Port) defer dcm.StopServer() - var srcTagsList TagsList - var destTagsList TagsList + var ( + srcTagsList TagsList + destTagsList TagsList + ) resp, _ := srcClient.R().Get(srcBaseURL + "/v2/" + testImage + "/tags/list") So(resp, ShouldNotBeNil) @@ -490,7 +497,7 @@ func TestOnDemand(t *testing.T) { So(err, ShouldBeNil) // sign using cosign - err = signature.SignImageUsingCosign(fmt.Sprintf("remote-repo@%s", manifestDigest.String()), port, false) + err = signature.SignImageUsingCosign("remote-repo@"+manifestDigest.String(), port, false) So(err, ShouldBeNil) // add cosign sbom @@ -561,8 +568,8 @@ func TestOnDemand(t *testing.T) { }, // include self url, should be ignored URLs: []string{ - fmt.Sprintf("http://%s", hostname), destBaseURL, - srcBaseURL, fmt.Sprintf("http://localhost:%s", destPort), + "http://" + hostname, destBaseURL, + srcBaseURL, "http://localhost:" + destPort, }, TLSVerify: &tlsVerify, CertDir: "", @@ -710,8 +717,8 @@ func TestOnDemand(t *testing.T) { }, // include self url, should be ignored URLs: []string{ - fmt.Sprintf("http://%s", hostname), destBaseURL, - srcBaseURL, fmt.Sprintf("http://localhost:%s", destPort), + "http://" + hostname, destBaseURL, + srcBaseURL, "http://localhost:" + destPort, }, TLSVerify: &tlsVerify, CertDir: "", @@ -767,8 +774,10 @@ func TestOnDemand(t *testing.T) { func TestOnDemandWithScaleOutCluster(t *testing.T) { Convey("Given 2 downstream zots and one upstream, test that the cluster can sync images", t, func() { sctlr, srcBaseURL, _, _, srcClient := makeUpstreamServer(t, false, false) + scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // sync config for both downstreams. @@ -825,7 +834,7 @@ func TestOnDemandWithScaleOutCluster(t *testing.T) { baseURLs := []string{srcBaseURL, dctrl1BaseURL, dctrl2BaseURL} for clientIdx, client := range clients { - resp, err := client.R().Get(fmt.Sprintf("%s/v2/", baseURLs[clientIdx])) + resp, err := client.R().Get(baseURLs[clientIdx] + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -834,6 +843,7 @@ func TestOnDemandWithScaleOutCluster(t *testing.T) { // storage for each downstream should not have image data at the start. destDirs := []string{destDir1, destDir2} images := []string{testImage, testCveImage} + for _, image := range images { for _, destDir := range destDirs { _, err := os.Stat(path.Join(destDir, image)) @@ -938,6 +948,7 @@ func TestOnDemandWithScaleOutClusterWithReposNotAddedForSync(t *testing.T) { sctlr, srcBaseURL, _, _, srcClient := makeUpstreamServer(t, false, false) scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // sync config for both downstreams. @@ -992,7 +1003,7 @@ func TestOnDemandWithScaleOutClusterWithReposNotAddedForSync(t *testing.T) { baseURLs := []string{srcBaseURL, dctrl1BaseURL, dctrl2BaseURL} for clientIdx, client := range clients { - resp, err := client.R().Get(fmt.Sprintf("%s/v2/", baseURLs[clientIdx])) + resp, err := client.R().Get(baseURLs[clientIdx] + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -1001,6 +1012,7 @@ func TestOnDemandWithScaleOutClusterWithReposNotAddedForSync(t *testing.T) { // storage for each downstream should not have image data at the start. destDirs := []string{destDir1, destDir2} images := []string{testImage, testCveImage} + for _, image := range images { for _, destDir := range destDirs { _, err := os.Stat(path.Join(destDir, image)) @@ -1069,6 +1081,7 @@ func TestSyncReferenceInLoop(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() var tlsVerify bool @@ -1099,6 +1112,7 @@ func TestSyncReferenceInLoop(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() // we will push references in loop: image A -> sbom A -> oci artifact A -> sbom A (same sbom as before) @@ -1213,6 +1227,7 @@ func TestSyncWithNonDistributableBlob(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() var tlsVerify bool @@ -1264,6 +1279,7 @@ func TestSyncWithNonDistributableBlob(t *testing.T) { So(err, ShouldBeNil) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() time.Sleep(3 * time.Second) @@ -1288,6 +1304,7 @@ func TestDockerImagesAreSkipped(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() var tlsVerify bool @@ -1455,6 +1472,7 @@ func TestDockerImagesAreSkipped(t *testing.T) { indexManifest.Manifests = make([]ispec.Descriptor, 4) var indexManifestIdx int + for idx, manifestDesc := range newIndex.Manifests { if manifestDesc.MediaType == ispec.MediaTypeImageIndex { indexManifestContent, err := os.ReadFile(path.Join(srcDir, indexRepoName, "blobs/sha256", @@ -1467,8 +1485,11 @@ func TestDockerImagesAreSkipped(t *testing.T) { } } - var configBlobDigest godigest.Digest - var indexManifestContent []byte + var ( + configBlobDigest godigest.Digest + indexManifestContent []byte + ) + for idx, manifestDesc := range newIndex.Manifests { if manifestDesc.MediaType == ispec.MediaTypeImageManifest { manifestContent, err := os.ReadFile(path.Join(srcDir, indexRepoName, "blobs/sha256", @@ -1585,10 +1606,12 @@ func TestPeriodically(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := ".*" semver := true + var tlsVerify bool maxRetries := 1 @@ -1622,10 +1645,13 @@ func TestPeriodically(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() - var srcTagsList TagsList - var destTagsList TagsList + var ( + srcTagsList TagsList + destTagsList TagsList + ) resp, _ := srcClient.R().Get(srcBaseURL + "/v2/" + testImage + "/tags/list") So(resp, ShouldNotBeNil) @@ -1698,8 +1724,10 @@ func TestPeriodically(t *testing.T) { dcm.StartAndWait(dctlr.Config.HTTP.Port) defer dcm.StopServer() - var srcTagsList TagsList - var destTagsList TagsList + var ( + srcTagsList TagsList + destTagsList TagsList + ) resp, err := srcClient.R().Get(srcBaseURL + "/v2/" + testImage + "/tags/list") So(err, ShouldBeNil) @@ -1755,12 +1783,14 @@ func TestPeriodically(t *testing.T) { func TestPeriodicallyWithScaleOutCluster(t *testing.T) { Convey("Given a zot cluster with periodic sync enabled, test that instances sync only managed repos", t, func() { updateDuration, _ := time.ParseDuration("30m") + const zotAlpineTestImageName = "zot-alpine-test" sctlr, srcBaseURL, _, _, _ := makeUpstreamServer(t, false, false) scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // upload additional image to the upstream. @@ -1818,6 +1848,7 @@ func TestPeriodicallyWithScaleOutCluster(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() // downstream should not have any of the images in its storage. @@ -1841,6 +1872,7 @@ func TestPeriodicallyWithScaleOutCluster(t *testing.T) { So(err, ShouldBeNil) var destTagsList TagsList + err = json.Unmarshal(resp.Body(), &destTagsList) So(err, ShouldBeNil) @@ -1873,10 +1905,12 @@ func TestPermsDenied(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := ".*" semver := true + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -1968,11 +2002,13 @@ func TestConfigReloader(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() duration, _ := time.ParseDuration("3s") var tlsVerify bool + defaultVal := true syncRegistryConfig := syncconf.RegistryConfig{ @@ -2241,12 +2277,14 @@ func TestMandatoryAnnotations(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := ".*" - var semver bool tlsVerify := false + var semver bool + syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ { @@ -2336,12 +2374,14 @@ func TestBadTLS(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := ".*" - var semver bool tlsVerify := true + var semver bool + syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ { @@ -2368,6 +2408,7 @@ func TestBadTLS(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() found, err := test.ReadLogFileAndSearchString(dctlr.Config.Log.Output, @@ -2407,10 +2448,13 @@ func TestTLS(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() - var srcIndex ispec.Index - var destIndex ispec.Index + var ( + srcIndex ispec.Index + destIndex ispec.Index + ) srcBuf, err := os.ReadFile(path.Join(srcDir, testImage, "index.json")) if err != nil { @@ -2425,25 +2469,30 @@ func TestTLS(t *testing.T) { destClientCertDir := t.TempDir() destFilePath := path.Join(destClientCertDir, "ca.crt") + err = test.CopyFile(CACert, destFilePath) if err != nil { panic(err) } destFilePath = path.Join(destClientCertDir, "client.cert") + err = test.CopyFile(ClientCert, destFilePath) if err != nil { panic(err) } destFilePath = path.Join(destClientCertDir, "client.key") + err = test.CopyFile(ClientKey, destFilePath) if err != nil { panic(err) } regex := ".*" + var semver bool + tlsVerify := true syncRegistryConfig := syncconf.RegistryConfig{ @@ -2472,19 +2521,23 @@ func TestTLS(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() // wait till ready for { destBuf, _ := os.ReadFile(path.Join(destDir, testImage, "index.json")) _ = json.Unmarshal(destBuf, &destIndex) + time.Sleep(500 * time.Millisecond) + if len(destIndex.Manifests) > 0 { break } } var found bool + for _, manifest := range srcIndex.Manifests { if reflect.DeepEqual(manifest.Annotations, destIndex.Manifests[0].Annotations) { found = true @@ -2523,6 +2576,7 @@ func TestBearerAuth(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() registryName := sync.StripRegistryTransport(srcBaseURL) @@ -2554,10 +2608,13 @@ func TestBearerAuth(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() - var srcTagsList TagsList - var destTagsList TagsList + var ( + srcTagsList TagsList + destTagsList TagsList + ) resp, err := srcClient.R().Get(srcBaseURL + "/v2/") So(err, ShouldBeNil) @@ -2571,12 +2628,14 @@ func TestBearerAuth(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var goodToken authutils.AccessTokenResponse + err = json.Unmarshal(resp.Body(), &goodToken) So(err, ShouldBeNil) resp, err = srcClient.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(srcBaseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -2600,7 +2659,7 @@ func TestBearerAuth(t *testing.T) { err = json.Unmarshal(resp.Body(), &goodToken) So(err, ShouldBeNil) - resp, err = srcClient.R().SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + resp, err = srcClient.R().SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(srcBaseURL + "/v2/" + testImage + "/tags/list") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -2665,6 +2724,7 @@ func TestBearerAuth(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() registryName := sync.StripRegistryTransport(srcBaseURL) @@ -2696,10 +2756,13 @@ func TestBearerAuth(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() - var srcTagsList TagsList - var destTagsList TagsList + var ( + srcTagsList TagsList + destTagsList TagsList + ) resp, err := srcClient.R().Get(srcBaseURL + "/v2/") So(err, ShouldBeNil) @@ -2713,12 +2776,14 @@ func TestBearerAuth(t *testing.T) { So(err, ShouldBeNil) So(resp, ShouldNotBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) + var goodToken authutils.AccessTokenResponse + err = json.Unmarshal(resp.Body(), &goodToken) So(err, ShouldBeNil) resp, err = srcClient.R(). - SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(srcBaseURL + "/v2/") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -2742,7 +2807,7 @@ func TestBearerAuth(t *testing.T) { err = json.Unmarshal(resp.Body(), &goodToken) So(err, ShouldBeNil) - resp, err = srcClient.R().SetHeader("Authorization", fmt.Sprintf("Bearer %s", goodToken.AccessToken)). + resp, err = srcClient.R().SetHeader("Authorization", "Bearer "+goodToken.AccessToken). Get(srcBaseURL + "/v2/" + testImage + "/tags/list") So(err, ShouldBeNil) So(resp, ShouldNotBeNil) @@ -2820,8 +2885,10 @@ func TestBasicAuth(t *testing.T) { dcm.StartAndWait(dctlr.Config.HTTP.Port) defer dcm.StopServer() - var srcTagsList TagsList - var destTagsList TagsList + var ( + srcTagsList TagsList + destTagsList TagsList + ) resp, _ := srcClient.R().SetBasicAuth(username, password).Get(srcBaseURL + "/v2/" + testImage + "/tags/list") So(resp, ShouldNotBeNil) @@ -2885,6 +2952,7 @@ func TestBasicAuth(t *testing.T) { destConfig.Storage.RootDirectory = rootDir regex := ".*" + var semver bool registryName := sync.StripRegistryTransport(srcBaseURL) @@ -2924,6 +2992,7 @@ func TestBasicAuth(t *testing.T) { dctlr := api.NewController(destConfig) dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(destPort) + defer dcm.StopServer() found, err := test.ReadLogFileAndSearchString(dctlr.Config.Log.Output, @@ -2968,8 +3037,11 @@ func TestBasicAuth(t *testing.T) { }() regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ @@ -3067,8 +3139,10 @@ func TestBasicAuth(t *testing.T) { dcm.StartAndWait(dctlr.Config.HTTP.Port) defer dcm.StopServer() - var srcTagsList TagsList - var destTagsList TagsList + var ( + srcTagsList TagsList + destTagsList TagsList + ) resp, _ := srcClient.R().SetBasicAuth(username, password).Get(srcBaseURL + "/v2/" + testImage + "/tags/list") So(resp, ShouldNotBeNil) @@ -3126,8 +3200,11 @@ func TestBadURL(t *testing.T) { updateDuration, _ := time.ParseDuration("1h") regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ @@ -3156,6 +3233,7 @@ func TestBadURL(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -3172,9 +3250,11 @@ func TestNoImagesByRegex(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := "9.9.9" + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -3202,6 +3282,7 @@ func TestNoImagesByRegex(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := destClient.R().Get(destBaseURL + constants.RoutePrefix + testImage + "/manifests/" + testImageTag) @@ -3214,6 +3295,7 @@ func TestNoImagesByRegex(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusOK) var catalog catalog + err = json.Unmarshal(resp.Body(), &catalog) if err != nil { panic(err) @@ -3231,9 +3313,11 @@ func TestInvalidRegex(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := "[" + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -3262,6 +3346,7 @@ func TestInvalidRegex(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() found, err := test.ReadLogFileAndSearchString(dctlr.Config.Log.Output, @@ -3289,6 +3374,7 @@ func TestNotSemver(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // get manifest so we can update it with a semver non compliant tag @@ -3307,6 +3393,7 @@ func TestNotSemver(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusCreated) semver := true + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -3334,6 +3421,7 @@ func TestNotSemver(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() var destTagsList TagsList @@ -3347,6 +3435,7 @@ func TestNotSemver(t *testing.T) { if err != nil { panic(err) } + if len(destTagsList.Tags) > 0 { break } @@ -3367,12 +3456,14 @@ func TestInvalidCerts(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // copy client certs, use them in sync config clientCertDir := t.TempDir() destFilePath := path.Join(clientCertDir, "ca.crt") + err := test.CopyFile(CACert, destFilePath) if err != nil { panic(err) @@ -3390,12 +3481,14 @@ func TestInvalidCerts(t *testing.T) { } destFilePath = path.Join(clientCertDir, "client.cert") + err = test.CopyFile(ClientCert, destFilePath) if err != nil { panic(err) } destFilePath = path.Join(clientCertDir, "client.key") + err = test.CopyFile(ClientKey, destFilePath) if err != nil { panic(err) @@ -3425,6 +3518,7 @@ func TestInvalidCerts(t *testing.T) { dctlr, destBaseURL, _, destClient := makeDownstreamServer(t, false, syncConfig) dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -3440,6 +3534,7 @@ func TestCertsWithWrongPerms(t *testing.T) { clientCertDir := t.TempDir() destFilePath := path.Join(clientCertDir, "ca.crt") + err := test.CopyFile(CACert, destFilePath) if err != nil { panic(err) @@ -3449,12 +3544,14 @@ func TestCertsWithWrongPerms(t *testing.T) { So(err, ShouldBeNil) destFilePath = path.Join(clientCertDir, "client.cert") + err = test.CopyFile(ClientCert, destFilePath) if err != nil { panic(err) } destFilePath = path.Join(clientCertDir, "client.key") + err = test.CopyFile(ClientKey, destFilePath) if err != nil { panic(err) @@ -3498,6 +3595,7 @@ func TestCertsWithWrongPerms(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -3524,8 +3622,11 @@ func TestInvalidUrl(t *testing.T) { Convey("Verify sync invalid url", t, func() { updateDuration, _ := time.ParseDuration("30m") regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ @@ -3555,6 +3656,7 @@ func TestInvalidUrl(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -3571,11 +3673,15 @@ func TestInvalidTags(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ @@ -3605,6 +3711,7 @@ func TestInvalidTags(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + "invalid:tag") @@ -3642,11 +3749,15 @@ func TestSubPaths(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(srcPort) + defer scm.StopServer() regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ @@ -3701,6 +3812,7 @@ func TestSubPaths(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(destPort) + defer dcm.StopServer() var destTagsList TagsList @@ -3763,6 +3875,7 @@ func TestOnDemandRepoErr(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := resty.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -3777,12 +3890,16 @@ func TestOnDemandContentFiltering(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() Convey("Test image is filtered out by content", func() { regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ @@ -3811,6 +3928,7 @@ func TestOnDemandContentFiltering(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := resty.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -3821,6 +3939,7 @@ func TestOnDemandContentFiltering(t *testing.T) { Convey("Test image is not filtered out by content", func() { regex := ".*" semver := true + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -3865,12 +3984,16 @@ func TestConfigRules(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() Convey("Test periodically sync is disabled when pollInterval is not set", func() { regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ @@ -3908,6 +4031,7 @@ func TestConfigRules(t *testing.T) { Convey("Test periodically sync is disabled when content is not set", func() { var tlsVerify bool + updateDuration, _ := time.ParseDuration("30m") syncRegistryConfig := syncconf.RegistryConfig{ @@ -3972,10 +4096,12 @@ func TestMultipleURLs(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := ".*" semver := true + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -4004,10 +4130,13 @@ func TestMultipleURLs(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() - var srcTagsList TagsList - var destTagsList TagsList + var ( + srcTagsList TagsList + destTagsList TagsList + ) resp, _ := srcClient.R().Get(srcBaseURL + "/v2/" + testImage + "/tags/list") So(resp, ShouldNotBeNil) @@ -4048,6 +4177,7 @@ func TestNoURLsLeftInConfig(t *testing.T) { regex := ".*" semver := true + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -4076,6 +4206,7 @@ func TestNoURLsLeftInConfig(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/tags/list") @@ -4093,11 +4224,14 @@ func TestPeriodicallySignaturesErr(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // create repo, push and sign it - repoName := testSignedImage var digest godigest.Digest + + repoName := testSignedImage + So(func() { digest = pushRepo(srcBaseURL, repoName) }, ShouldNotPanic) splittedURL := strings.SplitAfter(srcBaseURL, ":") @@ -4115,8 +4249,11 @@ func TestPeriodicallySignaturesErr(t *testing.T) { So(func() { signImage(tdir, srcPort, repoName, digest) }, ShouldNotPanic) regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ @@ -4163,8 +4300,10 @@ func TestPeriodicallySignaturesErr(t *testing.T) { So(err, ShouldBeNil) dctlr, destBaseURL, _, _ := makeDownstreamServer(t, false, syncConfig) + dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() found, err := test.ReadLogFileAndSearchString(dctlr.Config.Log.Output, @@ -4261,6 +4400,7 @@ func TestPeriodicallySignaturesErr(t *testing.T) { // read manifest var artifactManifest ispec.Manifest + for _, ref := range referrers.Manifests { refPath := path.Join(srcDir, repoName, "blobs", string(ref.Digest.Algorithm()), ref.Digest.Encoded()) body, err := os.ReadFile(refPath) @@ -4335,6 +4475,7 @@ func TestPeriodicallySignaturesErr(t *testing.T) { Convey("of type OCI image", func() { //nolint: dupl // read manifest var artifactManifest ispec.Manifest + for _, ref := range referrers.Manifests { refPath := path.Join(srcDir, repoName, "blobs", string(ref.Digest.Algorithm()), ref.Digest.Encoded()) body, err := os.ReadFile(refPath) @@ -4397,6 +4538,7 @@ func TestPeriodicallySignaturesErr(t *testing.T) { Convey("of type OCI artifact", func() { //nolint: dupl // read manifest var artifactManifest ispec.Manifest + for _, ref := range referrers.Manifests { refPath := path.Join(srcDir, repoName, "blobs", string(ref.Digest.Algorithm()), ref.Digest.Encoded()) body, err := os.ReadFile(refPath) @@ -4516,11 +4658,14 @@ func TestSignatures(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // create repo, push and sign it - repoName := testSignedImage var digest godigest.Digest + + repoName := testSignedImage + So(func() { digest = pushRepo(srcBaseURL, repoName) }, ShouldNotPanic) splittedURL := strings.SplitAfter(srcBaseURL, ":") @@ -4597,8 +4742,12 @@ func TestSignatures(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusCreated) regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) + onlySigned := true syncRegistryConfig := syncconf.RegistryConfig{ @@ -4629,6 +4778,7 @@ func TestSignatures(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() // wait for sync @@ -4755,6 +4905,7 @@ func TestSignatures(t *testing.T) { So(err, ShouldBeNil) var artifactManifest ispec.Manifest + for _, ref := range referrers.Manifests { refPath := path.Join(srcDir, repoName, "blobs", string(ref.Digest.Algorithm()), ref.Digest.Encoded()) body, err := os.ReadFile(refPath) @@ -4947,6 +5098,7 @@ func TestSignatures(t *testing.T) { So(err, ShouldBeNil) var refManifest ispec.Manifest + for _, ref := range index.Manifests { refPath := path.Join(srcDir, repoName, "blobs", string(ref.Digest.Algorithm()), ref.Digest.Encoded()) body, err := os.ReadFile(refPath) @@ -5037,11 +5189,14 @@ func TestSignatures(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // create repo, push and sign it - repoName := testSignedImage var digest godigest.Digest + + repoName := testSignedImage + So(func() { digest = pushRepo(srcBaseURL, repoName) }, ShouldNotPanic) splittedURL := strings.SplitAfter(srcBaseURL, ":") @@ -5052,8 +5207,12 @@ func TestSignatures(t *testing.T) { So(err, ShouldBeNil) regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) + onlySigned := true syncRegistryConfig := syncconf.RegistryConfig{ @@ -5084,6 +5243,7 @@ func TestSignatures(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() // wait for sync @@ -5145,6 +5305,7 @@ func TestSyncedSignaturesMetaDB(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // Push an image @@ -5194,6 +5355,7 @@ func TestSyncedSignaturesMetaDB(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() // Trigger SyncOnDemand @@ -5241,6 +5403,7 @@ func TestOnDemandRetryGoroutine(t *testing.T) { regex := ".*" semver := true + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -5274,6 +5437,7 @@ func TestOnDemandRetryGoroutine(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -5318,10 +5482,12 @@ func TestOnDemandWithDigest(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := ".*" semver := true + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -5350,6 +5516,7 @@ func TestOnDemandWithDigest(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() // get manifest digest from source @@ -5369,6 +5536,7 @@ func TestOnDemandRetryGoroutineErr(t *testing.T) { Convey("Verify ondemand sync retries in background on error", t, func() { regex := ".*" semver := true + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -5402,6 +5570,7 @@ func TestOnDemandRetryGoroutineErr(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := destClient.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -5413,6 +5582,7 @@ func TestOnDemandRetryGoroutineErr(t *testing.T) { if err != nil { panic(err) } + if !found { data, err := os.ReadFile(dctlr.Config.Log.Output) So(err, ShouldBeNil) @@ -5477,6 +5647,7 @@ func TestOnDemandMultipleImage(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() callsNo := 5 @@ -5487,6 +5658,7 @@ func TestOnDemandMultipleImage(t *testing.T) { populatedDirs := make(map[string]bool) done := make(chan bool) + go func() { /* watch .sync local cache, make sure just one .sync/subdir is populated with image the channel from ondemand should prevent spawning multiple go routines for the same image*/ @@ -5525,6 +5697,7 @@ func TestOnDemandMultipleImage(t *testing.T) { break } + time.Sleep(500 * time.Millisecond) } @@ -5545,10 +5718,12 @@ func TestOnDemandPullsOnce(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := ".*" semver := true + var tlsVerify bool syncRegistryConfig := syncconf.RegistryConfig{ @@ -5577,11 +5752,13 @@ func TestOnDemandPullsOnce(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() var wg goSync.WaitGroup wg.Add(1) + go func(conv C) { defer wg.Done() resp, err := resty.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -5590,6 +5767,7 @@ func TestOnDemandPullsOnce(t *testing.T) { }(conv) wg.Add(1) + go func(conv C) { defer wg.Done() resp, err := resty.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -5598,6 +5776,7 @@ func TestOnDemandPullsOnce(t *testing.T) { }(conv) wg.Add(1) + go func(conv C) { defer wg.Done() resp, err := resty.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -5641,11 +5820,14 @@ func TestSignaturesOnDemand(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // create repo, push and sign it - repoName := testSignedImage var digest godigest.Digest + + repoName := testSignedImage + So(func() { digest = pushRepo(srcBaseURL, repoName) }, ShouldNotPanic) splittedURL := strings.SplitAfter(srcBaseURL, ":") @@ -5681,6 +5863,7 @@ func TestSignaturesOnDemand(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() // sync on demand @@ -5763,11 +5946,14 @@ func TestSignaturesOnDemand(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // create repo, push and sign it - repoName := testSignedImage var digest godigest.Digest + + repoName := testSignedImage + So(func() { digest = pushRepo(srcBaseURL, repoName) }, ShouldNotPanic) splittedURL := strings.SplitAfter(srcBaseURL, ":") @@ -5845,6 +6031,7 @@ func TestSignaturesOnDemand(t *testing.T) { } resp, err = resty.R().Get(destBaseURL + "/v2/" + testSignedImage + "/manifests/" + testImageTag) + So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusOK) @@ -5871,11 +6058,14 @@ func TestOnlySignaturesOnDemand(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // create repo, push and sign it - repoName := testSignedImage var digest godigest.Digest + + repoName := testSignedImage + So(func() { digest = pushRepo(srcBaseURL, repoName) }, ShouldNotPanic) splittedURL := strings.SplitAfter(srcBaseURL, ":") @@ -5914,6 +6104,7 @@ func TestOnlySignaturesOnDemand(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() // sync on demand @@ -5984,6 +6175,7 @@ func TestSyncOnlyDiff(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() var tlsVerify bool @@ -6070,6 +6262,7 @@ func TestSyncWithDiffDigest(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() var tlsVerify bool @@ -6152,7 +6345,7 @@ func TestSyncWithDiffDigest(t *testing.T) { loc := resp.Header().Get("Location") resp, err = resty.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest.String()). SetBody(blob). @@ -6184,6 +6377,7 @@ func TestSyncWithDiffDigest(t *testing.T) { So(resp.StatusCode(), ShouldEqual, http.StatusCreated) dcm.StartServer() + defer dcm.StopServer() test.WaitTillServerReady(destBaseURL) @@ -6215,11 +6409,14 @@ func TestSyncSignaturesDiff(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() // create repo, push and sign it - repoName := testSignedImage var digest godigest.Digest + + repoName := testSignedImage + So(func() { digest = pushRepo(srcBaseURL, repoName) }, ShouldNotPanic) splittedURL := strings.SplitAfter(srcBaseURL, ":") @@ -6237,8 +6434,11 @@ func TestSyncSignaturesDiff(t *testing.T) { So(func() { signImage(tdir, srcPort, repoName, digest) }, ShouldNotPanic) regex := ".*" - var semver bool - var tlsVerify bool + + var ( + semver bool + tlsVerify bool + ) syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ @@ -6267,6 +6467,7 @@ func TestSyncSignaturesDiff(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() // wait for sync @@ -6312,8 +6513,10 @@ func TestSyncSignaturesDiff(t *testing.T) { // now add new signatures to upstream and let sync detect that upstream signatures changed and pull them So(os.RemoveAll(tdir), ShouldBeNil) + tdir = t.TempDir() defer os.RemoveAll(tdir) + _ = os.Chdir(tdir) generateKeyPairs(tdir) So(func() { signImage(tdir, srcPort, repoName, digest) }, ShouldNotPanic) @@ -6333,12 +6536,15 @@ func TestSyncSignaturesDiff(t *testing.T) { KeyRef: path.Join(tdir, "cosign.pub"), IgnoreTlog: true, } + err = vrfy.Exec(context.TODO(), []string{fmt.Sprintf("localhost:%s/%s:%s", destPort, repoName, testImageTag)}) So(err, ShouldBeNil) // compare signatures - var srcIndex ispec.Index - var destIndex ispec.Index + var ( + srcIndex ispec.Index + destIndex ispec.Index + ) srcBuf, err := os.ReadFile(path.Join(srcDir, repoName, "index.json")) if err != nil { @@ -6359,10 +6565,12 @@ func TestSyncSignaturesDiff(t *testing.T) { } // find image manifest digest (signed-repo) and upstream notary digests - var upstreamRefsDigests []string - var downstreamRefsDigests []string + var ( + upstreamRefsDigests []string + downstreamRefsDigests []string + manifestDigest string + ) - var manifestDigest string for _, manifestDesc := range srcIndex.Manifests { if manifestDesc.Annotations[ispec.AnnotationRefName] == testImageTag { manifestDigest = string(manifestDesc.Digest) @@ -6485,6 +6693,7 @@ func TestOnlySignedFlag(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() found, err := test.ReadLogFileAndSearchString(dctlr.Config.Log.Output, @@ -6520,6 +6729,7 @@ func TestOnlySignedFlag(t *testing.T) { dcm := test.NewControllerManager(dctlr) dcm.StartAndWait(dctlr.Config.HTTP.Port) + defer dcm.StopServer() resp, err := client.R().Get(destBaseURL + "/v2/" + testImage + "/manifests/" + testImageTag) @@ -6586,6 +6796,7 @@ func TestSyncWithDestination(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() splittedURL := strings.SplitAfter(srcBaseURL, ":") @@ -6729,12 +6940,14 @@ func TestSyncImageIndex(t *testing.T) { scm := test.NewControllerManager(sctlr) scm.StartAndWait(sctlr.Config.HTTP.Port) + defer scm.StopServer() regex := ".*" - var semver bool tlsVerify := false + var semver bool + syncRegistryConfig := syncconf.RegistryConfig{ Content: []syncconf.Content{ { @@ -6955,7 +7168,7 @@ func pushRepo(url, repoName string) godigest.Digest { resp, err = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -6984,7 +7197,7 @@ func pushRepo(url, repoName string) godigest.Digest { resp, err = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -7151,14 +7364,14 @@ func pushBlob(url string, repoName string, buf []byte) godigest.Digest { loc := test.Location(url, resp) digest := godigest.FromBytes(buf) + resp, err = resty.R(). SetContentLength(true). - SetHeader("Content-Length", fmt.Sprintf("%d", len(buf))). + SetHeader("Content-Length", strconv.Itoa(len(buf))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest.String()). SetBody(buf). Put(loc) - if err != nil { panic(err) } diff --git a/pkg/log/log.go b/pkg/log/log.go index 2ae1a3e5..40520558 100644 --- a/pkg/log/log.go +++ b/pkg/log/log.go @@ -46,6 +46,7 @@ func NewLogger(level, output string) Logger { if err != nil { panic(err) } + log = zerolog.New(file) } diff --git a/pkg/log/log_test.go b/pkg/log/log_test.go index 79216d70..a6b8f7aa 100644 --- a/pkg/log/log_test.go +++ b/pkg/log/log_test.go @@ -55,7 +55,9 @@ func TestAuditLogMessages(t *testing.T) { username, seedUser := test.GenerateRandomString() password, seedPass := test.GenerateRandomString() htpasswdPath := test.MakeHtpasswdFileFromString(test.GetCredString(username, password)) + defer os.Remove(htpasswdPath) + conf.HTTP.Auth = &config.AuthConfig{ HTPasswd: config.AuthHTPasswd{ Path: htpasswdPath, @@ -98,15 +100,19 @@ func TestAuditLogMessages(t *testing.T) { // wait until the file is populated byteValue, _ := io.ReadAll(auditFile) + for { if len(byteValue) != 0 { break } + time.Sleep(100 * time.Millisecond) + byteValue, _ = io.ReadAll(auditFile) } var auditLog AuditLog + err = json.Unmarshal(byteValue, &auditLog) if err != nil { panic(err) @@ -131,15 +137,19 @@ func TestAuditLogMessages(t *testing.T) { // wait until the file is populated byteValue, _ := io.ReadAll(auditFile) + for { if len(byteValue) != 0 { break } + time.Sleep(100 * time.Millisecond) + byteValue, _ = io.ReadAll(auditFile) } var auditLog AuditLog + err = json.Unmarshal(byteValue, &auditLog) if err != nil { panic(err) @@ -166,11 +176,14 @@ func TestAuditLogMessages(t *testing.T) { // wait until the file is populated byteValue, _ = io.ReadAll(auditFile) + for { if len(byteValue) != 0 { break } + time.Sleep(100 * time.Millisecond) + byteValue, _ = io.ReadAll(auditFile) } @@ -194,11 +207,14 @@ func TestAuditLogMessages(t *testing.T) { // wait until the file is populated byteValue, _ = io.ReadAll(auditFile) + for { if len(byteValue) != 0 { break } + time.Sleep(100 * time.Millisecond) + byteValue, _ = io.ReadAll(auditFile) } @@ -227,15 +243,19 @@ func TestAuditLogMessages(t *testing.T) { // wait until the file is populated byteValue, _ := io.ReadAll(auditFile) + for { if len(byteValue) != 0 { break } + time.Sleep(100 * time.Millisecond) + byteValue, _ = io.ReadAll(auditFile) } var auditLog AuditLog + err = json.Unmarshal(byteValue, &auditLog) if err != nil { panic(err) @@ -257,16 +277,20 @@ func TestAuditLogMessages(t *testing.T) { resp, err = resty.R().SetBasicAuth(username, password). SetHeader("Content-Type", "application/octet-stream"). SetHeader("Content-Range", contentRange).SetBody(chunk).Patch(loc) + So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusAccepted) // wait until the file is populated byteValue, _ = io.ReadAll(auditFile) + for { if len(byteValue) != 0 { break } + time.Sleep(100 * time.Millisecond) + byteValue, _ = io.ReadAll(auditFile) } diff --git a/pkg/meta/boltdb/boltdb.go b/pkg/meta/boltdb/boltdb.go index 736e7152..22edebd9 100644 --- a/pkg/meta/boltdb/boltdb.go +++ b/pkg/meta/boltdb/boltdb.go @@ -1268,6 +1268,7 @@ func (bdw *BoltDB) UpdateSignaturesValidity(ctx context.Context, repo string, ma } manifestSignatures := proto_go.ManifestSignatures{Map: map[string]*proto_go.SignaturesInfo{"": {}}} + for sigType, sigs := range protoRepoMeta.Signatures[manifestDigest.String()].Map { if zcommon.IsContextDone(ctx) { return ctx.Err() @@ -1378,6 +1379,7 @@ func (bdw *BoltDB) RemoveRepoReference(repo, reference string, manifestDigest go /* try to find at least one tag pointing to manifestDigest if not found then we can also remove everything related to this digest */ var foundTag bool + for _, desc := range protoRepoMeta.Tags { if desc.Digest == manifestDigest.String() { foundTag = true @@ -1883,6 +1885,7 @@ func (bdw *BoltDB) DeleteUserAPIKey(ctx context.Context, keyID string) error { func (bdw *BoltDB) GetUserAPIKeyInfo(hashedKey string) (string, error) { var userid string + err := bdw.DB.View(func(tx *bbolt.Tx) error { buck := tx.Bucket([]byte(UserAPIKeysBucket)) if buck == nil { diff --git a/pkg/meta/boltdb/boltdb_test.go b/pkg/meta/boltdb/boltdb_test.go index f2e8428c..60074bb3 100644 --- a/pkg/meta/boltdb/boltdb_test.go +++ b/pkg/meta/boltdb/boltdb_test.go @@ -105,6 +105,7 @@ func TestWrapperErrors(t *testing.T) { Convey("UpdateSignaturesValidity", func() { boltdbWrapper.SetImageTrustStore(imgTrustStore{}) + digest := image.Digest() ctx := context.Background() @@ -689,6 +690,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": true, }) + ctx := userAc.DeriveContext(context.Background()) err := boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error { @@ -711,6 +713,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": true, }) + ctx := userAc.DeriveContext(context.Background()) _, err = boltdbWrapper.ToggleStarRepo(ctx, "repo") @@ -814,6 +817,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": true, }) + ctx := userAc.DeriveContext(context.Background()) err = boltdbWrapper.DB.Update(func(tx *bbolt.Tx) error { diff --git a/pkg/meta/convert/convert_proto.go b/pkg/meta/convert/convert_proto.go index cd9a86b6..59ea2668 100644 --- a/pkg/meta/convert/convert_proto.go +++ b/pkg/meta/convert/convert_proto.go @@ -34,6 +34,7 @@ func GetProtoImageMeta(imageMeta mTypes.ImageMeta) *proto_go.ImageMeta { if len(imageMeta.Manifests) == 0 { return nil } + manifestData := imageMeta.Manifests[0] return GetProtoImageManifestData(manifestData.Manifest, manifestData.Config, manifestData.Size, diff --git a/pkg/meta/dynamodb/dynamodb.go b/pkg/meta/dynamodb/dynamodb.go index 58528554..4bf96484 100644 --- a/pkg/meta/dynamodb/dynamodb.go +++ b/pkg/meta/dynamodb/dynamodb.go @@ -1415,6 +1415,7 @@ func (dwr *DynamoDB) RemoveRepoReference(repo, reference string, manifestDigest } else { // find all tags pointing to this digest tags := []string{} + for tag, desc := range protoRepoMeta.Tags { if desc.Digest == reference { tags = append(tags, tag) @@ -1454,6 +1455,7 @@ func (dwr *DynamoDB) RemoveRepoReference(repo, reference string, manifestDigest if err != nil { return err } + err = dwr.setProtoRepoMeta(repo, protoRepoMeta) //nolint: contextcheck return err @@ -1519,7 +1521,6 @@ func (dwr *DynamoDB) ToggleBookmarkRepo(ctx context.Context, repo string) ( func (dwr *DynamoDB) GetBookmarkedRepos(ctx context.Context) ([]string, error) { userMeta, err := dwr.GetUserData(ctx) - if errors.Is(err, zerr.ErrUserDataNotFound) || errors.Is(err, zerr.ErrUserDataNotAllowed) { return []string{}, nil } @@ -1634,7 +1635,6 @@ func (dwr *DynamoDB) ToggleStarRepo(ctx context.Context, repo string) ( func (dwr *DynamoDB) GetStarredRepos(ctx context.Context) ([]string, error) { userMeta, err := dwr.GetUserData(ctx) - if errors.Is(err, zerr.ErrUserDataNotFound) || errors.Is(err, zerr.ErrUserDataNotAllowed) { return []string{}, nil } @@ -2179,7 +2179,6 @@ func (dwr *DynamoDB) createVersionTable() error { TableName: aws.String(dwr.VersionTablename), UpdateExpression: aws.String("SET #V = :Version"), }) - if err != nil { return err } diff --git a/pkg/meta/dynamodb/dynamodb_internal_test.go b/pkg/meta/dynamodb/dynamodb_internal_test.go index f187a7a3..5dc26d58 100644 --- a/pkg/meta/dynamodb/dynamodb_internal_test.go +++ b/pkg/meta/dynamodb/dynamodb_internal_test.go @@ -12,7 +12,7 @@ import ( "github.com/rs/zerolog" . "github.com/smartystreets/goconvey/convey" - "zotregistry.dev/zot/pkg/log" //nolint:go-staticcheck + "zotregistry.dev/zot/pkg/log" "zotregistry.dev/zot/pkg/meta/version" tskip "zotregistry.dev/zot/pkg/test/skip" ) @@ -21,6 +21,7 @@ func TestWrapperErrors(t *testing.T) { tskip.SkipDynamo(t) const region = "us-east-2" + endpoint := os.Getenv("DYNAMODBMOCK_ENDPOINT") uuid, err := guuid.NewV4() diff --git a/pkg/meta/dynamodb/dynamodb_test.go b/pkg/meta/dynamodb/dynamodb_test.go index 39a60c65..adb45308 100644 --- a/pkg/meta/dynamodb/dynamodb_test.go +++ b/pkg/meta/dynamodb/dynamodb_test.go @@ -32,6 +32,7 @@ func TestIterator(t *testing.T) { tskip.SkipDynamo(t) const region = "us-east-2" + endpoint := os.Getenv("DYNAMODBMOCK_ENDPOINT") uuid, err := guuid.NewV4() @@ -710,6 +711,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": false, }) + ctx := userAc.DeriveContext(context.Background()) _, err := dynamoWrapper.ToggleBookmarkRepo(ctx, "unaccesible") @@ -722,6 +724,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": true, }) + ctx := userAc.DeriveContext(context.Background()) status, err := dynamoWrapper.ToggleBookmarkRepo(ctx, "repo") @@ -735,6 +738,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": false, }) + ctx := userAc.DeriveContext(context.Background()) dynamoWrapper.UserDataTablename = badTablename @@ -750,6 +754,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": false, }) + ctx := userAc.DeriveContext(context.Background()) repos, err := dynamoWrapper.GetBookmarkedRepos(ctx) @@ -771,6 +776,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": false, }) + ctx := userAc.DeriveContext(context.Background()) _, err := dynamoWrapper.ToggleStarRepo(ctx, "unaccesible") @@ -783,6 +789,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": false, }) + ctx := userAc.DeriveContext(context.Background()) dynamoWrapper.UserDataTablename = badTablename @@ -797,6 +804,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": true, }) + ctx := userAc.DeriveContext(context.Background()) dynamoWrapper.RepoMetaTablename = badTablename @@ -821,6 +829,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": true, }) + ctx := userAc.DeriveContext(context.Background()) dynamoWrapper.UserDataTablename = badTablename @@ -835,6 +844,7 @@ func TestWrapperErrors(t *testing.T) { userAc.SetGlobPatterns("read", map[string]bool{ "repo": true, }) + ctx := userAc.DeriveContext(context.Background()) err := setBadUserData(dynamoWrapper.Client, userDataTablename, userAc.GetUsername()) @@ -911,6 +921,7 @@ func TestWrapperErrors(t *testing.T) { Convey("unmarshal error", func() { err := setRepoLastUpdated("repo", []byte("bad-blob"), dynamoWrapper) So(err, ShouldBeNil) + lastUpdated := dynamoWrapper.GetRepoLastUpdated("repo") So(lastUpdated, ShouldEqual, time.Time{}) }) diff --git a/pkg/meta/dynamodb/iterator.go b/pkg/meta/dynamodb/iterator.go index 969f4339..93f19246 100644 --- a/pkg/meta/dynamodb/iterator.go +++ b/pkg/meta/dynamodb/iterator.go @@ -59,7 +59,7 @@ func (dii *BaseAttributesIterator) First(ctx context.Context) (types.AttributeVa } if len(scanOutput.Items) == 0 { - return nil, nil + return nil, nil //nolint:nilnil } dii.itemBuffer = scanOutput.Items @@ -72,7 +72,7 @@ func (dii *BaseAttributesIterator) First(ctx context.Context) (types.AttributeVa func (dii *BaseAttributesIterator) Next(ctx context.Context) (types.AttributeValue, error) { if len(dii.itemBuffer) <= dii.currentItemIndex { if dii.lastEvaluatedKey == nil { - return nil, nil + return nil, nil //nolint:nilnil } scanOutput, err := dii.Client.Scan(ctx, &dynamodb.ScanInput{ @@ -85,7 +85,7 @@ func (dii *BaseAttributesIterator) Next(ctx context.Context) (types.AttributeVal // all items have been scanned if len(scanOutput.Items) == 0 { - return nil, nil + return nil, nil //nolint:nilnil } dii.itemBuffer = scanOutput.Items diff --git a/pkg/meta/hooks.go b/pkg/meta/hooks.go index 74fe3e0d..ccd373d9 100644 --- a/pkg/meta/hooks.go +++ b/pkg/meta/hooks.go @@ -72,6 +72,7 @@ func OnDeleteManifest(repo, reference, mediaType string, digest godigest.Digest, if err != nil { log.Error().Err(err).Str("component", "metadb"). Msg("failed to check if image is a signature or not") + manageRepoMetaSuccessfully = false } } else { diff --git a/pkg/meta/meta_test.go b/pkg/meta/meta_test.go index 7749c04d..c918bf4b 100644 --- a/pkg/meta/meta_test.go +++ b/pkg/meta/meta_test.go @@ -48,11 +48,12 @@ func getManifestDigest(md mTypes.ManifestMeta) string { return md.Digest.String( func TestBoltDB(t *testing.T) { Convey("BoltDB creation", t, func() { boltDBParams := boltdb.DBParameters{RootDir: t.TempDir()} + repoDBPath := path.Join(boltDBParams.RootDir, "meta.db") + defer os.Remove(repoDBPath) boltDriver, err := boltdb.GetBoltDriver(boltDBParams) So(err, ShouldBeNil) - defer os.Remove(repoDBPath) log := log.NewLogger("debug", "") @@ -505,8 +506,6 @@ func RunMetaDBTests(t *testing.T, metaDB mTypes.MetaDB, preparationFuncs ...func retrievedImgMultiData, err := metaDB.GetImageMeta(imgMulti.Digest()) So(err, ShouldBeNil) So(imgMulti.AsImageMeta(), ShouldEqual, retrievedImgMultiData) - - // set subject on multiarch }) Convey("GetFullImageMeta", func() { @@ -1378,8 +1377,8 @@ func RunMetaDBTests(t *testing.T, metaDB mTypes.MetaDB, preparationFuncs ...func ShouldResemble, "digest") imageMeta, err := metaDB.GetImageMeta(image1.Digest) - fullImageMeta := convert.GetFullImageMeta(tag1, repoMeta, imageMeta) + So(err, ShouldBeNil) So(fullImageMeta.Signatures["cosign"][0].SignatureManifestDigest, ShouldResemble, "digesttag") So(fullImageMeta.Signatures["cosign"][0].LayersInfo[0].LayerDigest, ShouldResemble, "layer-digest") @@ -1503,7 +1502,7 @@ func RunMetaDBTests(t *testing.T, metaDB mTypes.MetaDB, preparationFuncs ...func certificateContent, err := os.ReadFile(path.Join( tdir, "notation/localkeys", - fmt.Sprintf("%s.crt", keyName), + keyName+".crt", )) So(err, ShouldBeNil) So(certificateContent, ShouldNotBeNil) @@ -1602,7 +1601,9 @@ func RunMetaDBTests(t *testing.T, metaDB mTypes.MetaDB, preparationFuncs ...func image3 = CreateRandomImage() ctx = context.Background() ) + _ = repo3 + Convey("Search all repos", func() { err := metaDB.SetRepoReference(ctx, repo1, tag1, image1.AsImageMeta()) So(err, ShouldBeNil) @@ -1688,6 +1689,7 @@ func RunMetaDBTests(t *testing.T, metaDB mTypes.MetaDB, preparationFuncs ...func repoMetaList, err := metaDB.SearchRepos(ctx, "repo") //nolint: contextcheck So(err, ShouldBeNil) So(len(repoMetaList), ShouldEqual, 2) + for _, k := range repoMetaList { So(k.Name, ShouldBeIn, []string{repo1, repo2}) } diff --git a/pkg/meta/parse_test.go b/pkg/meta/parse_test.go index 7c997f18..09bb40ee 100644 --- a/pkg/meta/parse_test.go +++ b/pkg/meta/parse_test.go @@ -348,6 +348,7 @@ func RunParseStorageTests(rootDir string, metaDB mTypes.MetaDB, log log.Logger) storeController := storage.StoreController{DefaultStore: imageStore} manifests := []ispec.Manifest{} + for i := 0; i < 3; i++ { image := CreateRandomImage() //nolint:staticcheck @@ -389,6 +390,7 @@ func RunParseStorageTests(rootDir string, metaDB mTypes.MetaDB, log log.Logger) } } } + buf, err = json.Marshal(index) So(err, ShouldBeNil) @@ -429,6 +431,7 @@ func RunParseStorageTests(rootDir string, metaDB mTypes.MetaDB, log log.Logger) // add mock cosign signature without pushing the signed image image = CreateRandomImage() + So(err, ShouldBeNil) signatureTag, err := signature.GetCosignSignatureTagForManifest(image.Manifest) diff --git a/pkg/meta/proto/gen/config.pb.go b/pkg/meta/proto/gen/config.pb.go index 60cafd21..585edb9d 100644 --- a/pkg/meta/proto/gen/config.pb.go +++ b/pkg/meta/proto/gen/config.pb.go @@ -7,11 +7,12 @@ package gen import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/meta/proto/gen/descriptor.pb.go b/pkg/meta/proto/gen/descriptor.pb.go index e2c1a054..86439123 100644 --- a/pkg/meta/proto/gen/descriptor.pb.go +++ b/pkg/meta/proto/gen/descriptor.pb.go @@ -7,10 +7,11 @@ package gen import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/pkg/meta/proto/gen/index.pb.go b/pkg/meta/proto/gen/index.pb.go index 9e5d2a2b..758cd0ed 100644 --- a/pkg/meta/proto/gen/index.pb.go +++ b/pkg/meta/proto/gen/index.pb.go @@ -7,10 +7,11 @@ package gen import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/pkg/meta/proto/gen/manifest.pb.go b/pkg/meta/proto/gen/manifest.pb.go index f4640ced..9208077d 100644 --- a/pkg/meta/proto/gen/manifest.pb.go +++ b/pkg/meta/proto/gen/manifest.pb.go @@ -7,10 +7,11 @@ package gen import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/pkg/meta/proto/gen/meta.pb.go b/pkg/meta/proto/gen/meta.pb.go index 4c7b1eca..3d55e887 100644 --- a/pkg/meta/proto/gen/meta.pb.go +++ b/pkg/meta/proto/gen/meta.pb.go @@ -7,11 +7,12 @@ package gen import ( + reflect "reflect" + sync "sync" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" - reflect "reflect" - sync "sync" ) const ( diff --git a/pkg/meta/proto/gen/versioned.pb.go b/pkg/meta/proto/gen/versioned.pb.go index df7d9272..630747f5 100644 --- a/pkg/meta/proto/gen/versioned.pb.go +++ b/pkg/meta/proto/gen/versioned.pb.go @@ -7,10 +7,11 @@ package gen import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" ) const ( diff --git a/pkg/meta/version/version_test.go b/pkg/meta/version/version_test.go index 630877e1..e3bb26bd 100644 --- a/pkg/meta/version/version_test.go +++ b/pkg/meta/version/version_test.go @@ -34,6 +34,7 @@ func TestVersioningBoltDB(t *testing.T) { log := log.NewLogger("debug", "") boltdbWrapper, err := boltdb.New(boltDriver, log) + defer os.Remove(path.Join(boltDBParams.RootDir, "meta.db")) So(boltdbWrapper, ShouldNotBeNil) So(err, ShouldBeNil) diff --git a/pkg/retention/matcher.go b/pkg/retention/matcher.go index 2eeec935..b37176a5 100644 --- a/pkg/retention/matcher.go +++ b/pkg/retention/matcher.go @@ -28,6 +28,7 @@ func (r *RegexMatcher) MatchesListOfRegex(name string, regexes []string) bool { // all are compilable because they are checked at startup if tagReg, err := regexp.Compile(regex); err == nil { r.compiled[regex] = tagReg + if tagReg.MatchString(name) { return true } diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go index 9b98d6c0..bf165898 100644 --- a/pkg/scheduler/scheduler.go +++ b/pkg/scheduler/scheduler.go @@ -136,6 +136,7 @@ func (scheduler *Scheduler) poolWorker(ctx context.Context) { scheduler.tasksLock.Lock() scheduler.tasksDoWork++ scheduler.tasksLock.Unlock() + workStart = time.Now() } @@ -148,6 +149,7 @@ func (scheduler *Scheduler) poolWorker(ctx context.Context) { scheduler.tasksLock.Lock() scheduler.tasksDoWork-- scheduler.tasksLock.Unlock() + workDuration = time.Since(workStart) monitoring.ObserveWorkersTasksDuration(scheduler.metricServer, task.Name(), workDuration) } @@ -201,6 +203,7 @@ func (scheduler *Scheduler) metricsWorker() { monitoring.SetSchedulerGenerators(scheduler.metricServer, genMap) monitoring.SetSchedulerTasksQueue(scheduler.metricServer, tasksMap) + workersMap := make(map[string]int) scheduler.tasksLock.Lock() @@ -523,7 +526,7 @@ func (gen *generator) getState() State { func (gen *generator) getRanking() float64 { // take into account the priority, but also how many tasks of // a specific generator were executed in the current generator run - return math.Pow(10, float64(gen.priority)) / (1 + float64(gen.taskCount)) //nolint:gomnd + return math.Pow(10, float64(gen.priority)) / (1 + float64(gen.taskCount)) //nolint:mnd } func (scheduler *Scheduler) SubmitGenerator(taskGenerator TaskGenerator, interval time.Duration, priority Priority) { diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go index 8a3adaf2..0a4b1068 100644 --- a/pkg/scheduler/scheduler_test.go +++ b/pkg/scheduler/scheduler_test.go @@ -71,11 +71,12 @@ func (g *generator) Next() (scheduler.Task, error) { if g.step > g.limit { g.done = true } + g.step++ g.index++ if g.step%11 == 0 { - return nil, nil + return nil, nil //nolint:nilnil } if g.step%13 == 0 { @@ -266,8 +267,9 @@ func TestScheduler(t *testing.T) { } if strings.Contains(line, "executing medium") { - if !strings.Contains(line, fmt.Sprintf("executing medium %s", lastMediumGenerator)) { + if !strings.Contains(line, "executing medium "+lastMediumGenerator) { samePriorityFlippedCounter++ + if lastMediumGenerator == "1" { lastMediumGenerator = "2" } else { @@ -276,8 +278,9 @@ func TestScheduler(t *testing.T) { } } - if !strings.Contains(line, fmt.Sprintf("executing %s", lastPriority)) { + if !strings.Contains(line, "executing "+lastPriority) { priorityFlippedCounter++ + if lastPriority == "low" { lastPriority = "medium" } else { @@ -436,6 +439,7 @@ func TestGetNumWorkers(t *testing.T) { logger := log.NewLogger("debug", "logFile") metrics := monitoring.NewMetricsServer(true, logger) sch := scheduler.NewScheduler(config.New(), metrics, logger) + defer os.Remove("logFile") So(sch.NumWorkers, ShouldEqual, runtime.NumCPU()*4) }) @@ -446,6 +450,7 @@ func TestGetNumWorkers(t *testing.T) { logger := log.NewLogger("debug", "logFile") metrics := monitoring.NewMetricsServer(true, logger) sch := scheduler.NewScheduler(cfg, metrics, logger) + defer os.Remove("logFile") So(sch.NumWorkers, ShouldEqual, 3) }) diff --git a/pkg/storage/cache.go b/pkg/storage/cache.go index 8722671e..eed2ab4d 100644 --- a/pkg/storage/cache.go +++ b/pkg/storage/cache.go @@ -10,7 +10,7 @@ import ( func CreateCacheDatabaseDriver(storageConfig config.StorageConfig, log zlog.Logger) (cache.Cache, error) { if !storageConfig.Dedupe && storageConfig.StorageDriver == nil { - return nil, nil + return nil, nil //nolint:nilnil } // local cache @@ -29,13 +29,13 @@ func CreateCacheDatabaseDriver(storageConfig config.StorageConfig, log zlog.Logg if !ok { log.Warn().Msg("remote cache driver name missing!") - return nil, nil + return nil, nil //nolint:nilnil } if name != constants.DynamoDBDriverName { log.Warn().Str("driver", name).Msg("remote cache driver unsupported!") - return nil, nil + return nil, nil //nolint:nilnil } // dynamodb @@ -47,7 +47,7 @@ func CreateCacheDatabaseDriver(storageConfig config.StorageConfig, log zlog.Logg return Create("dynamodb", dynamoParams, log) } - return nil, nil + return nil, nil //nolint:nilnil } func Create(dbtype string, parameters interface{}, log zlog.Logger) (cache.Cache, error) { diff --git a/pkg/storage/cache/boltdb.go b/pkg/storage/cache/boltdb.go index b80bbcb8..8d0fc8be 100644 --- a/pkg/storage/cache/boltdb.go +++ b/pkg/storage/cache/boltdb.go @@ -50,7 +50,7 @@ func NewBoltDBCache(parameters interface{}, log zlog.Logger) (*BoltDBDriver, err FreelistType: bbolt.FreelistArrayType, } - cacheDB, err := bbolt.Open(dbPath, 0o600, dbOpts) //nolint:gomnd + cacheDB, err := bbolt.Open(dbPath, 0o600, dbOpts) //nolint:mnd if err != nil { if strings.Contains(err.Error(), "timeout") { err := fmt.Errorf("%w: %w, path '%s'", zerr.ErrTimeout, zerr.ErrDatabaseFileAlreadyInUse, dbPath) diff --git a/pkg/storage/cache/dynamodb.go b/pkg/storage/cache/dynamodb.go index ea8def92..84270a6a 100644 --- a/pkg/storage/cache/dynamodb.go +++ b/pkg/storage/cache/dynamodb.go @@ -32,7 +32,7 @@ type Blob struct { } func (d *DynamoDBDriver) NewTable(tableName string) error { - //nolint:gomnd + //nolint:mnd _, err := d.client.CreateTable(context.TODO(), &dynamodb.CreateTableInput{ TableName: &tableName, AttributeDefinitions: []types.AttributeDefinition{ diff --git a/pkg/storage/cache/dynamodb_test.go b/pkg/storage/cache/dynamodb_test.go index 3f4158a5..91166b7d 100644 --- a/pkg/storage/cache/dynamodb_test.go +++ b/pkg/storage/cache/dynamodb_test.go @@ -208,8 +208,10 @@ func TestDynamoDBError(t *testing.T) { _, err = cacheDriver.GetBlob(godigest.FromString("str")) So(err, ShouldNotBeNil) + found := cacheDriver.HasBlob(godigest.FromString("str"), "path") So(found, ShouldBeFalse) + _, err = cacheDriver.GetDuplicateBlob(godigest.FromString("str")) So(err, ShouldNotBeNil) err = cacheDriver.DeleteBlob(godigest.FromString("str"), "path") diff --git a/pkg/storage/cache_benchmark_test.go b/pkg/storage/cache_benchmark_test.go index d48905fc..0b149b59 100644 --- a/pkg/storage/cache_benchmark_test.go +++ b/pkg/storage/cache_benchmark_test.go @@ -36,6 +36,7 @@ func generateData() map[godigest.Digest]string { rs, _ := test.GenerateRandomString() randomString += rs } + digest := godigest.FromString(randomString) dataMap[digest] = randomString } diff --git a/pkg/storage/common/common.go b/pkg/storage/common/common.go index 3565e857..58131194 100644 --- a/pkg/storage/common/common.go +++ b/pkg/storage/common/common.go @@ -234,6 +234,7 @@ func CheckIfIndexNeedsUpdate(index *ispec.Index, desc *ispec.Descriptor, log.Error().Err(err). Str("old mediaType", manifest.MediaType). Str("new mediaType", desc.MediaType).Msg("cannot change media-type") + reason := fmt.Sprintf("changing manifest media-type from \"%s\" to \"%s\" is disallowed", manifest.MediaType, desc.MediaType) @@ -860,7 +861,7 @@ func (gen *DedupeTaskGenerator) Next() (scheduler.Task, error) { // no repositories in storage, no need to continue gen.done = true - return nil, nil + return nil, nil //nolint:nilnil } } @@ -878,7 +879,7 @@ func (gen *DedupeTaskGenerator) Next() (scheduler.Task, error) { gen.done = true - return nil, nil + return nil, nil //nolint:nilnil } // mark digest as processed before running its task @@ -975,8 +976,9 @@ func (gen *StorageMetricsInitGenerator) Next() (scheduler.Task, error) { if repo == "" { gen.done = true - return nil, nil + return nil, nil //nolint:nilnil } + gen.lastRepo = repo return NewStorageMetricsTask(gen.ImgStore, gen.Metrics, repo, gen.Log), nil diff --git a/pkg/storage/common/common_test.go b/pkg/storage/common/common_test.go index af340084..c618d762 100644 --- a/pkg/storage/common/common_test.go +++ b/pkg/storage/common/common_test.go @@ -98,7 +98,9 @@ func TestValidateManifest(t *testing.T) { _, _, err = imgStore.PutImageManifest("test", "1.0", ispec.MediaTypeImageManifest, body) So(err, ShouldNotBeNil) + var internalErr *zerr.Error + So(errors.As(err, &internalErr), ShouldBeTrue) So(internalErr.GetDetails(), ShouldContainKey, "jsonSchemaValidation") So(internalErr.GetDetails()["jsonSchemaValidation"], ShouldEqual, "[schemaVersion: Must be less than or equal to 2]") diff --git a/pkg/storage/gc/gc.go b/pkg/storage/gc/gc.go index cc693d81..4dd2ecfe 100644 --- a/pkg/storage/gc/gc.go +++ b/pkg/storage/gc/gc.go @@ -81,19 +81,19 @@ It also gc untagged manifests. */ func (gc GarbageCollect) CleanRepo(ctx context.Context, repo string) error { gc.log.Info().Str("module", "gc"). - Msg(fmt.Sprintf("executing GC of orphaned blobs for %s", path.Join(gc.imgStore.RootDir(), repo))) + Msg("executing gc of orphaned blobs for " + path.Join(gc.imgStore.RootDir(), repo)) if err := gc.cleanRepo(ctx, repo); err != nil { - errMessage := fmt.Sprintf("failed to run GC for %s", path.Join(gc.imgStore.RootDir(), repo)) + errMessage := "failed to run GC for " + path.Join(gc.imgStore.RootDir(), repo) gc.log.Error().Err(err).Str("module", "gc").Msg(errMessage) gc.log.Info().Str("module", "gc"). - Msg(fmt.Sprintf("GC unsuccessfully completed for %s", path.Join(gc.imgStore.RootDir(), repo))) + Msg("gc unsuccessfully completed for " + path.Join(gc.imgStore.RootDir(), repo)) return err } gc.log.Info().Str("module", "gc"). - Msg(fmt.Sprintf("GC successfully completed for %s", path.Join(gc.imgStore.RootDir(), repo))) + Msg("gc successfully completed for " + path.Join(gc.imgStore.RootDir(), repo)) return nil } @@ -787,7 +787,7 @@ func (gen *GCTaskGenerator) Next() (scheduler.Task, error) { if repo == "" { gen.done = true - return nil, nil + return nil, nil //nolint:nilnil } gen.lastRepo = repo diff --git a/pkg/storage/gc/gc_internal_test.go b/pkg/storage/gc/gc_internal_test.go index ba535f16..3bd40287 100644 --- a/pkg/storage/gc/gc_internal_test.go +++ b/pkg/storage/gc/gc_internal_test.go @@ -199,6 +199,7 @@ func TestGarbageCollectIndexErrors(t *testing.T) { index.MediaType = ispec.MediaTypeImageIndex var digest godigest.Digest + for i := 0; i < 4; i++ { // upload image config blob upload, err := imgStore.NewBlobUpload(repoName) @@ -234,6 +235,7 @@ func TestGarbageCollectIndexErrors(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) _, _, err = imgStore.PutImageManifest(repoName, digest.String(), ispec.MediaTypeImageManifest, content) @@ -249,6 +251,7 @@ func TestGarbageCollectIndexErrors(t *testing.T) { // upload index image indexContent, err := json.Marshal(index) So(err, ShouldBeNil) + indexDigest := godigest.FromBytes(indexContent) So(indexDigest, ShouldNotBeNil) diff --git a/pkg/storage/imagestore/imagestore.go b/pkg/storage/imagestore/imagestore.go index 86ea2e76..7275abdc 100644 --- a/pkg/storage/imagestore/imagestore.go +++ b/pkg/storage/imagestore/imagestore.go @@ -2,6 +2,7 @@ package imagestore import ( "context" + "encoding/hex" "encoding/json" "errors" "fmt" @@ -224,7 +225,7 @@ func (is *ImageStore) ValidateRepo(name string) (bool, error) { return false, zerr.ErrRepoNotFound } - //nolint:gomnd + //nolint:mnd if len(files) < 2 { return false, zerr.ErrRepoBadVersion } @@ -951,7 +952,7 @@ func (is *ImageStore) FullBlobUpload(repo string, body io.Reader, dstDigest godi return "", -1, err } - srcDigest := godigest.NewDigestFromEncoded(dstDigestAlgorithm, fmt.Sprintf("%x", digester.Sum(nil))) + srcDigest := godigest.NewDigestFromEncoded(dstDigestAlgorithm, hex.EncodeToString(digester.Sum(nil))) if srcDigest != dstDigest { is.log.Error().Str("srcDigest", srcDigest.String()). Str("dstDigest", dstDigest.String()).Msg("actual digest not equal to expected digest") @@ -1125,7 +1126,7 @@ func (is *ImageStore) GetAllDedupeReposCandidates(digest godigest.Digest) ([]str } if is.cache == nil { - return nil, nil + return nil, nil //nolint:nilnil } is.RLock(&lockLatency) @@ -1996,7 +1997,7 @@ func (is *ImageStore) PopulateStorageMetrics(interval time.Duration, sch *schedu ImgStore: is, Metrics: is.metrics, Log: is.log, - MaxDelay: 15, //nolint:gomnd + MaxDelay: 15, //nolint:mnd } sch.SubmitGenerator(generator, interval, scheduler.HighPriority) diff --git a/pkg/storage/local/driver.go b/pkg/storage/local/driver.go index 528152ed..9963d4d0 100644 --- a/pkg/storage/local/driver.go +++ b/pkg/storage/local/driver.go @@ -162,6 +162,7 @@ func (driver *Driver) Writer(filepath string, append bool) (storagedriver.FileWr return nil, driver.formatErr(err) } + offset = n } @@ -207,9 +208,9 @@ func (driver *Driver) Walk(path string, walkFn storagedriver.WalkFn) error { return err } } + err = walkFn(fileInfo) - //nolint: gocritic - if err == nil && fileInfo.IsDir() { + if err == nil && fileInfo.IsDir() { //nolint: gocritic if err := driver.Walk(child, walkFn); err != nil { return err } diff --git a/pkg/storage/local/driver_test.go b/pkg/storage/local/driver_test.go index 4e0e5aca..d1e18d85 100644 --- a/pkg/storage/local/driver_test.go +++ b/pkg/storage/local/driver_test.go @@ -35,6 +35,7 @@ func TestStorageDriver(t *testing.T) { fileName := "testFile" _, err := os.Create(path.Join(rootDir, fileName)) So(err, ShouldBeNil) + result = driver.DirExists(path.Join(rootDir, fileName)) So(result, ShouldBeFalse) diff --git a/pkg/storage/local/local_elevated_test.go b/pkg/storage/local/local_elevated_test.go index a9b0eef3..0ea8ffb2 100644 --- a/pkg/storage/local/local_elevated_test.go +++ b/pkg/storage/local/local_elevated_test.go @@ -83,6 +83,7 @@ func TestElevatedPrivilegesInvalidDedupe(t *testing.T) { So(blob, ShouldEqual, buflen) cmd := exec.Command("chattr", "+i", path.Join(dir, "dedupe2", "blobs/sha256", blobDigest1)) //nolint: gosec + _, err = cmd.Output() if err != nil { panic(err) @@ -93,6 +94,7 @@ func TestElevatedPrivilegesInvalidDedupe(t *testing.T) { So(blob, ShouldEqual, buflen) cmd = exec.Command("chattr", "-i", path.Join(dir, "dedupe2", "blobs/sha256", blobDigest1)) //nolint: gosec + _, err = cmd.Output() if err != nil { panic(err) diff --git a/pkg/storage/local/local_test.go b/pkg/storage/local/local_test.go index 1c5ae89b..44579f79 100644 --- a/pkg/storage/local/local_test.go +++ b/pkg/storage/local/local_test.go @@ -110,6 +110,7 @@ func TestStorageFSAPIs(t *testing.T) { _, clen, err := imgStore.FullBlobUpload(repoName, bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err := imgStore.CheckBlob(repoName, cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -133,6 +134,7 @@ func TestStorageFSAPIs(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err := json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(manifestBuf) err = os.Chmod(path.Join(imgStore.RootDir(), repoName, "index.json"), 0o000) @@ -176,6 +178,7 @@ func TestStorageFSAPIs(t *testing.T) { _, _, err = imgStore.PutImageManifest(repoName, "2.0", ispec.MediaTypeImageManifest, manifestBuf) So(err, ShouldNotBeNil) + err = os.Chmod(path.Join(imgStore.RootDir(), repoName), 0o755) if err != nil { panic(err) @@ -183,6 +186,7 @@ func TestStorageFSAPIs(t *testing.T) { // invalid DeleteImageManifest indexPath := path.Join(imgStore.RootDir(), repoName, "index.json") + err = os.Chmod(indexPath, 0o000) if err != nil { panic(err) @@ -204,6 +208,7 @@ func FuzzNewBlobUpload(f *testing.F) { dir := t.TempDir() defer os.RemoveAll(dir) t.Logf("Input argument is %s", data) + log := zlog.Logger{Logger: zerolog.New(os.Stdout)} metrics := monitoring.NewMetricsServer(false, log) cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{ @@ -230,6 +235,7 @@ func FuzzPutBlobChunk(f *testing.F) { dir := t.TempDir() defer os.RemoveAll(dir) t.Logf("Input argument is %s", data) + log := zlog.Logger{Logger: zerolog.New(os.Stdout)} metrics := monitoring.NewMetricsServer(false, log) @@ -241,6 +247,7 @@ func FuzzPutBlobChunk(f *testing.F) { imgStore := local.NewImageStore(dir, true, true, log, metrics, nil, cacheDriver) repoName := data + uuid, err := imgStore.NewBlobUpload(repoName) if err != nil { if isKnownErr(err) { @@ -252,6 +259,7 @@ func FuzzPutBlobChunk(f *testing.F) { buf := bytes.NewBufferString(data) buflen := buf.Len() + _, err = imgStore.PutBlobChunk(repoName, uuid, 0, int64(buflen), buf) if err != nil { t.Error(err) @@ -264,6 +272,7 @@ func FuzzPutBlobChunkStreamed(f *testing.F) { dir := t.TempDir() defer os.RemoveAll(dir) t.Logf("Input argument is %s", data) + log := zlog.Logger{Logger: zerolog.New(os.Stdout)} metrics := monitoring.NewMetricsServer(false, log) cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{ @@ -285,6 +294,7 @@ func FuzzPutBlobChunkStreamed(f *testing.F) { } buf := bytes.NewBufferString(data) + _, err = imgStore.PutBlobChunkStreamed(repoName, uuid, buf) if err != nil { t.Error(err) @@ -311,6 +321,7 @@ func FuzzGetBlobUpload(f *testing.F) { if errors.Is(err, zerr.ErrUploadNotFound) || isKnownErr(err) { return } + t.Error(err) } }) @@ -342,6 +353,7 @@ func FuzzTestPutGetImageManifest(f *testing.F) { if err != nil { t.Error(err) } + _, _, err = imgStore.FullBlobUpload(repoName, bytes.NewReader(lblob), ldigest) if err != nil { t.Error(err) @@ -351,15 +363,19 @@ func FuzzTestPutGetImageManifest(f *testing.F) { if err != nil { t.Error(err) } + manifestBuf, err := json.Marshal(manifest) if err != nil { t.Errorf("Error %v occurred while marshaling manifest", err) } + mdigest := godigest.FromBytes(manifestBuf) + _, _, err = imgStore.PutImageManifest(repoName, mdigest.String(), ispec.MediaTypeImageManifest, manifestBuf) if err != nil && errors.Is(err, zerr.ErrBadManifest) { t.Errorf("the error that occurred is %v \n", err) } + _, _, _, err = imgStore.GetImageManifest(repoName, mdigest.String()) if err != nil { t.Errorf("the error that occurred is %v \n", err) @@ -408,7 +424,9 @@ func FuzzTestPutDeleteImageManifest(f *testing.F) { if err != nil { t.Errorf("Error %v occurred while marshaling manifest", err) } + mdigest := godigest.FromBytes(manifestBuf) + _, _, err = imgStore.PutImageManifest(repoName, mdigest.String(), ispec.MediaTypeImageManifest, manifestBuf) if err != nil && errors.Is(err, zerr.ErrBadManifest) { t.Errorf("the error that occurred is %v \n", err) @@ -419,6 +437,7 @@ func FuzzTestPutDeleteImageManifest(f *testing.F) { if isKnownErr(err) { return } + t.Errorf("the error that occurred is %v \n", err) } }) @@ -444,11 +463,13 @@ func FuzzTestDeleteImageManifest(f *testing.F) { if err != nil { return } + err = imgStore.DeleteImageManifest(string(data), digest.String(), false) if err != nil { if errors.Is(err, zerr.ErrRepoNotFound) || isKnownErr(err) { return } + t.Error(err) } }) @@ -474,11 +495,13 @@ func FuzzInitRepo(f *testing.F) { UseRelPaths: true, }, *log) imgStore := local.NewImageStore(dir, true, true, *log, metrics, nil, cacheDriver) + err := imgStore.InitRepo(data) if err != nil { if isKnownErr(err) { return } + t.Error(err) } }) @@ -498,18 +521,22 @@ func FuzzInitValidateRepo(f *testing.F) { UseRelPaths: true, }, *log) imgStore := local.NewImageStore(dir, true, true, *log, metrics, nil, cacheDriver) + err := imgStore.InitRepo(data) if err != nil { if isKnownErr(err) { return } + t.Error(err) } + _, err = imgStore.ValidateRepo(data) if err != nil { if errors.Is(err, zerr.ErrRepoNotFound) || errors.Is(err, zerr.ErrRepoBadVersion) || isKnownErr(err) { return } + t.Error(err) } }) @@ -529,11 +556,13 @@ func FuzzGetImageTags(f *testing.F) { UseRelPaths: true, }, *log) imgStore := local.NewImageStore(dir, true, true, *log, metrics, nil, cacheDriver) + _, err := imgStore.GetImageTags(data) if err != nil { if errors.Is(err, zerr.ErrRepoNotFound) || isKnownErr(err) { return } + t.Error(err) } }) @@ -579,6 +608,7 @@ func FuzzBlobUploadInfo(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } }) @@ -607,6 +637,7 @@ func FuzzTestGetImageManifest(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } }) @@ -633,6 +664,7 @@ func FuzzFinishBlobUpload(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } @@ -646,6 +678,7 @@ func FuzzFinishBlobUpload(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } @@ -654,6 +687,7 @@ func FuzzFinishBlobUpload(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } }) @@ -685,6 +719,7 @@ func FuzzFullBlobUpload(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } }) @@ -793,6 +828,7 @@ func FuzzDeleteBlobUpload(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } @@ -846,8 +882,10 @@ func FuzzCheckBlob(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } + _, _, err = imgStore.CheckBlob(repoName, digest) if err != nil { t.Error(err) @@ -877,6 +915,7 @@ func FuzzGetBlob(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } @@ -885,8 +924,10 @@ func FuzzGetBlob(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } + if err = blobReadCloser.Close(); err != nil { t.Error(err) } @@ -915,6 +956,7 @@ func FuzzDeleteBlob(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } @@ -923,6 +965,7 @@ func FuzzDeleteBlob(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } }) @@ -950,6 +993,7 @@ func FuzzGetIndexContent(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } @@ -958,6 +1002,7 @@ func FuzzGetIndexContent(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } }) @@ -985,6 +1030,7 @@ func FuzzGetBlobContent(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } @@ -993,6 +1039,7 @@ func FuzzGetBlobContent(f *testing.F) { if isKnownErr(err) { return } + t.Error(err) } }) @@ -1004,6 +1051,7 @@ func FuzzRunGCRepo(f *testing.F) { audit := zlog.NewAuditLogger("debug", "") metrics := monitoring.NewMetricsServer(false, log) + dir := t.TempDir() defer os.RemoveAll(dir) @@ -1085,6 +1133,7 @@ func TestDedupeLinks(t *testing.T) { blob, err := imgStore.PutBlobChunkStreamed("dedupe1", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest1 := strings.Split(digest.String(), ":")[1] So(blobDigest1, ShouldNotBeEmpty) @@ -1104,6 +1153,7 @@ func TestDedupeLinks(t *testing.T) { _, clen, err := imgStore.FullBlobUpload("dedupe1", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err := imgStore.CheckBlob("dedupe1", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -1125,6 +1175,7 @@ func TestDedupeLinks(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err := json.Marshal(manifest) So(err, ShouldBeNil) + manifestDigest := godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest("dedupe1", manifestDigest.String(), ispec.MediaTypeImageManifest, manifestBuf) @@ -1145,6 +1196,7 @@ func TestDedupeLinks(t *testing.T) { blob, err = imgStore.PutBlobChunkStreamed("dedupe2", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest2 := strings.Split(digest.String(), ":")[1] So(blobDigest2, ShouldNotBeEmpty) @@ -1164,6 +1216,7 @@ func TestDedupeLinks(t *testing.T) { _, clen, err = imgStore.FullBlobUpload("dedupe2", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err = imgStore.CheckBlob("dedupe2", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -1185,6 +1238,7 @@ func TestDedupeLinks(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest("dedupe2", "1.0", ispec.MediaTypeImageManifest, manifestBuf) So(err, ShouldBeNil) @@ -1243,6 +1297,7 @@ func TestDedupeLinks(t *testing.T) { imgStore := local.NewImageStore(dir, true, true, log, metrics, nil, cacheDriver) imgStore.RunDedupeBlobs(time.Duration(0), taskScheduler) + sleepValue := i * 5 time.Sleep(time.Duration(sleepValue) * time.Millisecond) @@ -1391,6 +1446,7 @@ func TestDedupeLinks(t *testing.T) { blob, err = imgStore.PutBlobChunkStreamed("dedupe3", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest2 := strings.Split(digest.String(), ":")[1] So(blobDigest2, ShouldNotBeEmpty) @@ -1406,6 +1462,7 @@ func TestDedupe(t *testing.T) { Convey("Dedupe", t, func(c C) { Convey("Nil ImageStore", func() { var is storageTypes.ImageStore + So(func() { _ = is.DedupeBlob("", "", "", "") }, ShouldPanic) }) @@ -1442,6 +1499,7 @@ func TestNegativeCases(t *testing.T) { So(local.NewImageStore(dir, true, true, log, metrics, nil, cacheDriver), ShouldNotBeNil) + if os.Geteuid() != 0 { cacheDriver, _ := storage.Create("boltdb", cache.BoltDBDriverParameters{ RootDir: "/deadBEEF", @@ -1525,6 +1583,7 @@ func TestNegativeCases(t *testing.T) { if err != nil { panic(err) } + _, err = imgStore.ValidateRepo("invalid-test") So(err, ShouldNotBeNil) So(err, ShouldEqual, zerr.ErrRepoNotFound) @@ -1557,10 +1616,12 @@ func TestNegativeCases(t *testing.T) { if err != nil { panic(err) } + err = os.Mkdir(path.Join(dir, "invalid-test", "blobs"), 0o755) if err != nil { panic(err) } + isValid, err = imgStore.ValidateRepo("invalid-test") So(err, ShouldBeNil) So(isValid, ShouldEqual, true) @@ -1629,11 +1690,13 @@ func TestNegativeCases(t *testing.T) { So(imgStore, ShouldNotBeNil) So(imgStore.InitRepo("test"), ShouldBeNil) So(os.Remove(path.Join(dir, "test", "index.json")), ShouldBeNil) + _, err := imgStore.GetImageTags("test") So(err, ShouldNotBeNil) So(os.RemoveAll(path.Join(dir, "test")), ShouldBeNil) So(imgStore.InitRepo("test"), ShouldBeNil) So(os.WriteFile(path.Join(dir, "test", "index.json"), []byte{}, 0o600), ShouldBeNil) + _, err = imgStore.GetImageTags("test") So(err, ShouldNotBeNil) }) @@ -1681,6 +1744,7 @@ func TestNegativeCases(t *testing.T) { if err != nil { panic(err) } + _, _, _, err = imgStore.GetImageManifest("test", "") So(err, ShouldNotBeNil) }) @@ -1705,6 +1769,7 @@ func TestNegativeCases(t *testing.T) { if err != nil { panic(err) } + _, err = imgStore.NewBlobUpload("test") So(err, ShouldNotBeNil) @@ -1738,6 +1803,7 @@ func TestNegativeCases(t *testing.T) { if err != nil { panic(err) } + t.Cleanup(func() { err = os.Chmod(path.Join(dir, "test", ".uploads"), 0o700) if err != nil { @@ -1759,6 +1825,7 @@ func TestNegativeCases(t *testing.T) { dir := t.TempDir() filePath := path.Join(dir, "file.txt") + err := os.WriteFile(filePath, []byte("some dummy file content"), 0o644) //nolint: gosec if err != nil { panic(err) @@ -1784,6 +1851,7 @@ func TestNegativeCases(t *testing.T) { t.Fatal(err) } } + path := builder.String() ok := common.DirExists(path) So(ok, ShouldBeFalse) @@ -1799,12 +1867,14 @@ func TestHardLink(t *testing.T) { if err != nil { panic(err) } + randomDir = "/tmp/" + randSeq(int(nBig.Int64())) if _, err := os.Stat(randomDir); os.IsNotExist(err) { break } } + defer os.RemoveAll(randomDir) err := local.ValidateHardLink(randomDir) @@ -1814,6 +1884,7 @@ func TestHardLink(t *testing.T) { dir := t.TempDir() filePath := path.Join(dir, "file.txt") + err := os.WriteFile(filePath, []byte("some dummy file content"), 0o644) //nolint: gosec if err != nil { panic(err) @@ -1913,6 +1984,7 @@ func TestGarbageCollectForImageStore(t *testing.T) { So(err, ShouldBeNil) manifestDigest := image.ManifestDescriptor.Digest + err = os.Remove(path.Join(dir, repoName, "blobs", manifestDigest.Algorithm().String(), manifestDigest.Encoded())) if err != nil { @@ -1927,7 +1999,7 @@ func TestGarbageCollectForImageStore(t *testing.T) { data, err := os.ReadFile(logFile.Name()) So(err, ShouldBeNil) So(string(data), ShouldContainSubstring, - fmt.Sprintf("failed to run GC for %s", path.Join(imgStore.RootDir(), repoName))) + "failed to run GC for "+path.Join(imgStore.RootDir(), repoName)) }) Convey("Garbage collect error - not enough permissions to access index.json", func() { @@ -1969,7 +2041,7 @@ func TestGarbageCollectForImageStore(t *testing.T) { data, err := os.ReadFile(logFile.Name()) So(err, ShouldBeNil) So(string(data), ShouldContainSubstring, - fmt.Sprintf("failed to run GC for %s", path.Join(imgStore.RootDir(), repoName))) + "failed to run GC for "+path.Join(imgStore.RootDir(), repoName)) So(os.Chmod(path.Join(dir, repoName, "index.json"), 0o755), ShouldBeNil) }) @@ -2006,6 +2078,7 @@ func TestGarbageCollectForImageStore(t *testing.T) { So(err, ShouldBeNil) cosignSig := CreateRandomImage() + So(err, ShouldBeNil) err = WriteImageToFileSystem(cosignSig, repoName, cosignTag, storeController) @@ -2017,9 +2090,11 @@ func TestGarbageCollectForImageStore(t *testing.T) { manifestDigest := godigest.FromBytes(manifestBlob) sbomTag := fmt.Sprintf("sha256-%s.%s", manifestDigest.Encoded(), "sbom") + So(err, ShouldBeNil) sbomImg := CreateRandomImage() + So(err, ShouldBeNil) err = WriteImageToFileSystem(sbomImg, repoName, sbomTag, storeController) @@ -2266,9 +2341,11 @@ func TestGarbageCollectErrors(t *testing.T) { buflen := buf.Len() digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) + blob, err := imgStore.PutBlobChunkStreamed(repoName, upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + bdgst1 := digest bsize1 := len(content) @@ -2316,6 +2393,7 @@ func TestGarbageCollectErrors(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) _, _, err = imgStore.PutImageManifest(repoName, digest.String(), ispec.MediaTypeImageManifest, content) @@ -2331,6 +2409,7 @@ func TestGarbageCollectErrors(t *testing.T) { // upload index image indexContent, err := json.Marshal(index) So(err, ShouldBeNil) + indexDigest := godigest.FromBytes(indexContent) So(indexDigest, ShouldNotBeNil) @@ -2381,6 +2460,7 @@ func TestGarbageCollectErrors(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) @@ -2439,6 +2519,7 @@ func TestGarbageCollectErrors(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) @@ -2820,6 +2901,7 @@ func TestPutBlobChunkStreamed(t *testing.T) { So(err, ShouldBeNil) var reader io.Reader + blobPath := imgStore.BlobUploadPath("test", uuid) err = os.Chmod(blobPath, 0o000) So(err, ShouldBeNil) diff --git a/pkg/storage/s3/s3_test.go b/pkg/storage/s3/s3_test.go index a0ec1eb6..adc2045b 100644 --- a/pkg/storage/s3/s3_test.go +++ b/pkg/storage/s3/s3_test.go @@ -483,6 +483,7 @@ func TestGetOCIReferrers(t *testing.T) { blob, err := imgStore.PutBlobChunkStreamed(repo, upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest1 := digest So(blobDigest1, ShouldNotBeEmpty) @@ -698,8 +699,10 @@ func TestNegativeCasesObjectsStorage(t *testing.T) { So(storeDriver.Move(context.Background(), path.Join(testDir, testImage, "index.json"), path.Join(testDir, testImage, "blobs")), ShouldBeNil) + ok, _ := imgStore.ValidateRepo(testImage) So(ok, ShouldBeFalse) + _, err = imgStore.GetImageTags(testImage) So(err, ShouldNotBeNil) @@ -714,6 +717,7 @@ func TestNegativeCasesObjectsStorage(t *testing.T) { Convey("Without dedupe", t, func(c C) { tdir := t.TempDir() + storeDriver, imgStore, _ := createObjectsStore(testDir, tdir, false) defer cleanupStorage(storeDriver, testDir) @@ -740,6 +744,7 @@ func TestNegativeCasesObjectsStorage(t *testing.T) { So(imgStore.InitRepo(testImage), ShouldBeNil) So(storeDriver.Move(context.Background(), path.Join(testDir, testImage, "index.json"), path.Join(testDir, testImage, "_index.json")), ShouldBeNil) + ok, err := imgStore.ValidateRepo(testImage) So(err, ShouldBeNil) So(ok, ShouldBeFalse) @@ -1157,6 +1162,7 @@ func TestS3Dedupe(t *testing.T) { blob, err := imgStore.PutBlobChunkStreamed("dedupe1", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest1 := digest So(blobDigest1, ShouldNotBeEmpty) @@ -1185,6 +1191,7 @@ func TestS3Dedupe(t *testing.T) { _, clen, err := imgStore.FullBlobUpload("dedupe1", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err := imgStore.CheckBlob("dedupe1", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -1207,6 +1214,7 @@ func TestS3Dedupe(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err := json.Marshal(manifest) So(err, ShouldBeNil) + manifestDigest := godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest("dedupe1", manifestDigest.String(), ispec.MediaTypeImageManifest, manifestBuf) @@ -1228,6 +1236,7 @@ func TestS3Dedupe(t *testing.T) { blob, err = imgStore.PutBlobChunkStreamed("dedupe2", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest2 := digest So(blobDigest2, ShouldNotBeEmpty) @@ -1245,6 +1254,7 @@ func TestS3Dedupe(t *testing.T) { So(getBlobSize2, ShouldBeGreaterThan, 0) So(checkBlobSize1, ShouldEqual, checkBlobSize2) So(getBlobSize1, ShouldEqual, getBlobSize2) + err = blobReadCloser.Close() So(err, ShouldBeNil) @@ -1253,6 +1263,7 @@ func TestS3Dedupe(t *testing.T) { So(len(blobContent), ShouldBeGreaterThan, 0) So(checkBlobSize1, ShouldEqual, len(blobContent)) So(getBlobSize1, ShouldEqual, len(blobContent)) + err = blobReadCloser.Close() So(err, ShouldBeNil) @@ -1260,6 +1271,7 @@ func TestS3Dedupe(t *testing.T) { _, clen, err = imgStore.FullBlobUpload("dedupe2", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err = imgStore.CheckBlob("dedupe2", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -1281,6 +1293,7 @@ func TestS3Dedupe(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest("dedupe2", "1.0", ispec.MediaTypeImageManifest, manifestBuf) @@ -1379,6 +1392,7 @@ func TestS3Dedupe(t *testing.T) { blob, err = imgStore.PutBlobChunkStreamed("dedupe3", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest2 := digest So(blobDigest2, ShouldNotBeEmpty) @@ -1394,6 +1408,7 @@ func TestS3Dedupe(t *testing.T) { "application/vnd.oci.image.layer.v1.tar+gzip") So(err, ShouldBeNil) So(getBlobSize1, ShouldEqual, getBlobSize2) + err = blobReadCloser.Close() So(err, ShouldBeNil) @@ -1419,6 +1434,7 @@ func TestS3Dedupe(t *testing.T) { _, clen, err = imgStore.FullBlobUpload("dedupe3", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err = imgStore.CheckBlob("dedupe3", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -1440,6 +1456,7 @@ func TestS3Dedupe(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest("dedupe3", "1.0", ispec.MediaTypeImageManifest, manifestBuf) @@ -1568,6 +1585,7 @@ func TestS3Dedupe(t *testing.T) { blob, err := imgStore.PutBlobChunkStreamed("dedupe1", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest1 := digest So(blobDigest1, ShouldNotBeEmpty) @@ -1590,6 +1608,7 @@ func TestS3Dedupe(t *testing.T) { _, clen, err := imgStore.FullBlobUpload("dedupe1", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err := imgStore.CheckBlob("dedupe1", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -1612,6 +1631,7 @@ func TestS3Dedupe(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err := json.Marshal(manifest) So(err, ShouldBeNil) + manifestDigest := godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest("dedupe1", manifestDigest.String(), ispec.MediaTypeImageManifest, manifestBuf) @@ -1633,6 +1653,7 @@ func TestS3Dedupe(t *testing.T) { blob, err = imgStore.PutBlobChunkStreamed("dedupe2", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest2 := digest So(blobDigest2, ShouldNotBeEmpty) @@ -1650,6 +1671,7 @@ func TestS3Dedupe(t *testing.T) { So(getBlobSize2, ShouldBeGreaterThan, 0) So(checkBlobSize1, ShouldEqual, checkBlobSize2) So(getBlobSize1, ShouldEqual, getBlobSize2) + err = blobReadCloser.Close() So(err, ShouldBeNil) @@ -1657,6 +1679,7 @@ func TestS3Dedupe(t *testing.T) { _, clen, err = imgStore.FullBlobUpload("dedupe2", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err = imgStore.CheckBlob("dedupe2", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -1678,6 +1701,7 @@ func TestS3Dedupe(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest("dedupe2", "1.0", ispec.MediaTypeImageManifest, manifestBuf) @@ -1884,6 +1908,7 @@ func TestRebuildDedupeIndex(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err := json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest("dedupe1", digest.String(), ispec.MediaTypeImageManifest, manifestBuf) @@ -1967,6 +1992,7 @@ func TestRebuildDedupeIndex(t *testing.T) { // rebuild with dedupe false, should have all blobs with content imgStore.RunDedupeBlobs(time.Duration(0), taskScheduler) + sleepValue := i * 5 time.Sleep(time.Duration(sleepValue) * time.Millisecond) @@ -2067,6 +2093,7 @@ func TestRebuildDedupeIndex(t *testing.T) { Convey("Trigger Stat error while getting original blob", func() { tdir := t.TempDir() + storeDriver, imgStore, _ := createObjectsStore(testDir, tdir, false) defer cleanupStorage(storeDriver, testDir) @@ -2120,6 +2147,7 @@ func TestRebuildDedupeIndex(t *testing.T) { Convey("Trigger GetNextDigestWithBlobPaths path not found err", func() { tdir := t.TempDir() + storeDriver, imgStore, _ := createObjectsStore(testDir, tdir, true) defer cleanupStorage(storeDriver, testDir) @@ -2511,7 +2539,7 @@ func TestRebuildDedupeMockStoreDriver(t *testing.T) { tdir := t.TempDir() imgStore := createMockStorage(testDir, tdir, true, &StorageDriverMock{ StatFn: func(ctx context.Context, path string) (driver.FileInfo, error) { - if path == fmt.Sprintf("path/to/%s", validDigest.Encoded()) { + if path == "path/to/"+validDigest.Encoded() { return &FileInfoMock{ SizeFn: func() int64 { return int64(10) @@ -2607,7 +2635,7 @@ func TestRebuildDedupeMockStoreDriver(t *testing.T) { storageDriverMockElseBranch := &StorageDriverMock{ StatFn: func(ctx context.Context, path string) (driver.FileInfo, error) { - if path == fmt.Sprintf("path/to/%s", validDigest.Encoded()) { + if path == "path/to/"+validDigest.Encoded() { return &FileInfoMock{ SizeFn: func() int64 { return int64(10) @@ -2727,6 +2755,7 @@ func TestS3PullRange(t *testing.T) { buflen := buf.Len() digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) + blob, err := imgStore.PutBlobChunkStreamed("index", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) @@ -2797,6 +2826,7 @@ func TestS3PullRange(t *testing.T) { buflen := buf.Len() digest := godigest.FromBytes(dupcontent) So(digest, ShouldNotBeNil) + blob, err := imgStore.PutBlobChunkStreamed("dupindex", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) @@ -2903,9 +2933,11 @@ func TestS3ManifestImageIndex(t *testing.T) { buflen := buf.Len() digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) + blob, err := imgStore.PutBlobChunkStreamed("index", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + bdgst1 := digest bsize1 := len(content) @@ -2947,8 +2979,10 @@ func TestS3ManifestImageIndex(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) + m1content := content _, _, err = imgStore.PutImageManifest("index", "test:1.0", ispec.MediaTypeImageManifest, content) So(err, ShouldBeNil) @@ -2989,6 +3023,7 @@ func TestS3ManifestImageIndex(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) m2dgst := digest @@ -3031,6 +3066,7 @@ func TestS3ManifestImageIndex(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) _, _, err = imgStore.PutImageManifest("index", digest.String(), ispec.MediaTypeImageManifest, content) @@ -3053,6 +3089,7 @@ func TestS3ManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) index1dgst := digest @@ -3095,6 +3132,7 @@ func TestS3ManifestImageIndex(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) m4dgst := digest @@ -3118,8 +3156,10 @@ func TestS3ManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) + _, _, err = imgStore.PutImageManifest("index", "test:index2", ispec.MediaTypeImageIndex, content) So(err, ShouldBeNil) _, _, _, err = imgStore.GetImageManifest("index", "test:index2") @@ -3147,8 +3187,10 @@ func TestS3ManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) + _, _, err = imgStore.PutImageManifest("index", "test:index3", ispec.MediaTypeImageIndex, content) So(err, ShouldBeNil) _, _, _, err = imgStore.GetImageManifest("index", "test:index3") @@ -3168,6 +3210,7 @@ func TestS3ManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) _, _, err = imgStore.PutImageManifest("index", digest.String(), ispec.MediaTypeImageIndex, content) @@ -3220,6 +3263,7 @@ func TestS3ManifestImageIndex(t *testing.T) { buflen := buf.Len() digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) + blob, err := imgStore.PutBlobChunkStreamed("index", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) @@ -3246,6 +3290,7 @@ func TestS3ManifestImageIndex(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) _, _, err = imgStore.PutImageManifest("index", digest.String(), ispec.MediaTypeImageManifest, content) @@ -3264,8 +3309,10 @@ func TestS3ManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) + _, _, err = imgStore.PutImageManifest("index", "test:index1", ispec.MediaTypeImageIndex, content) So(err, ShouldBeNil) _, _, _, err = imgStore.GetImageManifest("index", "test:index1") @@ -3297,6 +3344,7 @@ func TestS3ManifestImageIndex(t *testing.T) { _, err = wrtr.Write([]byte("deadbeef")) So(err, ShouldBeNil) wrtr.Close() + err = imgStore.DeleteImageManifest("index", index1dgst.String(), false) So(err, ShouldBeNil) _, _, _, err = imgStore.GetImageManifest("index", "test:index1") @@ -3317,8 +3365,10 @@ func TestS3ManifestImageIndex(t *testing.T) { content, err = json.Marshal(index) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) + _, _, err = imgStore.PutImageManifest("index", "test:1.0", ispec.MediaTypeImageIndex, content) So(err, ShouldNotBeNil) @@ -3352,6 +3402,7 @@ func TestS3ManifestImageIndex(t *testing.T) { buflen := buf.Len() bdigest := godigest.FromBytes(content) bsize := len(content) + So(bdigest, ShouldNotBeNil) _, clen, err := imgStore.FullBlobUpload("index", buf, bdigest) @@ -3385,8 +3436,10 @@ func TestS3ManifestImageIndex(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + m1digest := godigest.FromBytes(content) So(m1digest, ShouldNotBeNil) + m1size := len(content) _, _, err = imgStore.PutImageManifest("index", "test:1.0", ispec.MediaTypeImageManifest, content) @@ -3419,15 +3472,16 @@ func TestS3ManifestImageIndex(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + m2digest := godigest.FromBytes(content) So(m2digest, ShouldNotBeNil) + m2size := len(content) _, _, err = imgStore.PutImageManifest("index", m2digest.String(), ispec.MediaTypeImageManifest, content) So(err, ShouldBeNil) Convey("Put image index with valid subject", func() { // create an image index containing the 2nd manifest, having the 1st manifest as subject - var index ispec.Index index.SchemaVersion = 2 index.Manifests = []ispec.Descriptor{ @@ -3445,6 +3499,7 @@ func TestS3ManifestImageIndex(t *testing.T) { content, err := json.Marshal(index) So(err, ShouldBeNil) + idigest := godigest.FromBytes(content) So(idigest, ShouldNotBeNil) @@ -3532,7 +3587,7 @@ func TestS3DedupeErr(t *testing.T) { return errS3 }, StatFn: func(ctx context.Context, path string) (driver.FileInfo, error) { - return nil, nil + return nil, nil //nolint:nilnil }, }) @@ -3548,7 +3603,7 @@ func TestS3DedupeErr(t *testing.T) { tdir := t.TempDir() imgStore = createMockStorage(testDir, tdir, true, &StorageDriverMock{ StatFn: func(ctx context.Context, path string) (driver.FileInfo, error) { - return nil, nil + return nil, nil //nolint:nilnil }, }) @@ -3567,7 +3622,7 @@ func TestS3DedupeErr(t *testing.T) { return errS3 }, StatFn: func(ctx context.Context, path string) (driver.FileInfo, error) { - return nil, nil + return nil, nil //nolint:nilnil }, }) @@ -3861,6 +3916,7 @@ func TestInjectDedupe(t *testing.T) { injected := inject.InjectFailure(0) err = imgStore.DedupeBlob("blob", "digest", "", "newblob") + if injected { So(err, ShouldNotBeNil) } else { @@ -3869,6 +3925,7 @@ func TestInjectDedupe(t *testing.T) { injected = inject.InjectFailure(1) err = imgStore.DedupeBlob("blob", "digest", "", "newblob") + if injected { So(err, ShouldNotBeNil) } else { diff --git a/pkg/storage/scrub.go b/pkg/storage/scrub.go index f00c9c0e..859252cb 100644 --- a/pkg/storage/scrub.go +++ b/pkg/storage/scrub.go @@ -207,7 +207,6 @@ func scrubManifest( } layersToScrub, err := scrubManifest(man, imgStore, imageName, tag, buf, scrubbedManifests) - if err == nil { layers = append(layers, layersToScrub...) } @@ -238,7 +237,6 @@ func scrubManifest( } layersToScrub, err := scrubManifest(*idx.Subject, imgStore, imageName, tag, buf, scrubbedManifests) - if err == nil { layers = append(layers, layersToScrub...) } @@ -272,7 +270,6 @@ func scrubManifest( } layersToScrub, err := scrubManifest(*man.Subject, imgStore, imageName, tag, buf, scrubbedManifests) - if err == nil { layers = append(layers, layersToScrub...) } diff --git a/pkg/storage/scrub_test.go b/pkg/storage/scrub_test.go index 11c9f392..cb0490a9 100644 --- a/pkg/storage/scrub_test.go +++ b/pkg/storage/scrub_test.go @@ -85,8 +85,10 @@ func RunCheckAllBlobsIntegrityTests( //nolint: thelper // initialize repo err := imgStore.InitRepo(repoName) So(err, ShouldBeNil) + ok := imgStore.DirExists(path.Join(imgStore.RootDir(), repoName)) So(ok, ShouldBeTrue) + storeCtlr := storage.StoreController{} storeCtlr.DefaultStore = imgStore So(storeCtlr.GetImageStore(repoName), ShouldResemble, imgStore) @@ -117,6 +119,7 @@ func RunCheckAllBlobsIntegrityTests( //nolint: thelper res, err = storeCtlr.CheckAllBlobsIntegrity(context.Background()) res.PrintScrubResults(buff) So(err, ShouldBeNil) + str = space.ReplaceAllString(buff.String(), " ") actual = strings.TrimSpace(str) So(actual, ShouldContainSubstring, "REPOSITORY TAG STATUS AFFECTED BLOB ERROR") diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 9391f7bc..79fbe4c8 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -218,8 +218,8 @@ func getSubStore(cfg *config.Config, subPaths map[string]config.StorageConfig, func compareImageStore(root1, root2 string) bool { isSameFile, err := config.SameFile(root1, root2) - // This error is path error that means either of root directory doesn't exist, in that case do string match if err != nil { + // This error is path error that means either of root directory doesn't exist, in that case do string match return strings.EqualFold(root1, root2) } diff --git a/pkg/storage/storage_controller.go b/pkg/storage/storage_controller.go index 35c8cdb8..721a1a60 100644 --- a/pkg/storage/storage_controller.go +++ b/pkg/storage/storage_controller.go @@ -1,7 +1,6 @@ package storage import ( - "fmt" "strings" storageTypes "zotregistry.dev/zot/pkg/storage/types" @@ -18,16 +17,16 @@ type StoreController struct { } func GetRoutePrefix(name string) string { - names := strings.SplitN(name, "/", 2) //nolint:gomnd + names := strings.SplitN(name, "/", 2) //nolint:mnd - if len(names) != 2 { //nolint:gomnd + if len(names) != 2 { //nolint:mnd // it means route is of global storage e.g "centos:latest" if len(names) == 1 { return "/" } } - return fmt.Sprintf("/%s", names[0]) + return "/" + names[0] } func (sc StoreController) GetImageStore(name string) storageTypes.ImageStore { diff --git a/pkg/storage/storage_test.go b/pkg/storage/storage_test.go index 12aee9ac..0fa8b640 100644 --- a/pkg/storage/storage_test.go +++ b/pkg/storage/storage_test.go @@ -138,6 +138,7 @@ func TestGetAllDedupeReposCandidates(t *testing.T) { testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var imgStore storageTypes.ImageStore + if testcase.storageType == storageConstants.S3StorageDriverName { tskip.SkipS3(t) @@ -207,6 +208,7 @@ func TestStorageAPIs(t *testing.T) { testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var imgStore storageTypes.ImageStore + if testcase.storageType == storageConstants.S3StorageDriverName { tskip.SkipS3(t) @@ -253,6 +255,7 @@ func TestStorageAPIs(t *testing.T) { v, err := imgStore.ValidateRepo(repoName) So(v, ShouldEqual, false) So(err, ShouldNotBeNil) + ok := imgStore.DirExists(path.Join(imgStore.RootDir(), repoName)) So(ok, ShouldBeFalse) }) @@ -260,8 +263,10 @@ func TestStorageAPIs(t *testing.T) { Convey("Initialize repo", func() { err := imgStore.InitRepo(repoName) So(err, ShouldBeNil) + ok := imgStore.DirExists(path.Join(imgStore.RootDir(), repoName)) So(ok, ShouldBeTrue) + storeController := storage.StoreController{} storeController.DefaultStore = imgStore So(storeController.GetImageStore("test"), ShouldResemble, imgStore) @@ -482,6 +487,7 @@ func TestStorageAPIs(t *testing.T) { _, clen, err := imgStore.FullBlobUpload("test", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err := imgStore.CheckBlob("test", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -507,6 +513,7 @@ func TestStorageAPIs(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest := godigest.FromBytes(manifestBuf) // bad manifest @@ -699,6 +706,7 @@ func TestStorageAPIs(t *testing.T) { _, clen, err := imgStore.FullBlobUpload("test", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err := imgStore.CheckBlob("test", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -720,6 +728,7 @@ func TestStorageAPIs(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest := godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest("test", digest.String(), ispec.MediaTypeImageManifest, manifestBuf) @@ -754,6 +763,7 @@ func TestStorageAPIs(t *testing.T) { So(err, ShouldBeNil) So(len(index.Manifests), ShouldEqual, 1) + err = imgStore.DeleteImageManifest("test", "1.0", false) So(err, ShouldNotBeNil) @@ -785,6 +795,7 @@ func TestStorageAPIs(t *testing.T) { blob, err := imgStore.PutBlobChunkStreamed("replace", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest1 := strings.Split(digest.String(), ":")[1] So(blobDigest1, ShouldNotBeEmpty) @@ -796,6 +807,7 @@ func TestStorageAPIs(t *testing.T) { _, clen, err := imgStore.FullBlobUpload("replace", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err := imgStore.CheckBlob("replace", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -837,6 +849,7 @@ func TestStorageAPIs(t *testing.T) { blob, err = imgStore.PutBlobChunkStreamed("replace", upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + blobDigest2 := strings.Split(digest.String(), ":")[1] So(blobDigest2, ShouldNotBeEmpty) @@ -848,6 +861,7 @@ func TestStorageAPIs(t *testing.T) { _, clen, err = imgStore.FullBlobUpload("replace", bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err = imgStore.CheckBlob("replace", cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -869,6 +883,7 @@ func TestStorageAPIs(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err = json.Marshal(manifest) So(err, ShouldBeNil) + _ = godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest("replace", "1.0", ispec.MediaTypeImageManifest, manifestBuf) So(err, ShouldBeNil) @@ -879,8 +894,10 @@ func TestStorageAPIs(t *testing.T) { var wg sync.WaitGroup for i := 0; i < 1000; i++ { wg.Add(2) + go func() { var lockLatency time.Time + defer wg.Done() imgStore.Lock(&lockLatency) func() {}() @@ -888,12 +905,14 @@ func TestStorageAPIs(t *testing.T) { }() go func() { var lockLatency time.Time + defer wg.Done() imgStore.RLock(&lockLatency) func() {}() imgStore.RUnlock(&lockLatency) }() } + wg.Wait() }) }) @@ -906,7 +925,9 @@ func TestMandatoryAnnotations(t *testing.T) { testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var imgStore storageTypes.ImageStore + var testDir, tdir string + var store driver.StorageDriver log := zlog.Logger{Logger: zerolog.New(os.Stdout)} @@ -1097,7 +1118,9 @@ func TestDeleteBlobsInUse(t *testing.T) { testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var imgStore storageTypes.ImageStore + var testDir, tdir string + var store driver.StorageDriver log := zlog.Logger{Logger: zerolog.New(os.Stdout)} @@ -1241,9 +1264,11 @@ func TestDeleteBlobsInUse(t *testing.T) { buflen := buf.Len() digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) + blob, err := imgStore.PutBlobChunkStreamed(repoName, upload, buf) So(err, ShouldBeNil) So(blob, ShouldEqual, buflen) + bdgst1 := digest bsize1 := len(content) @@ -1256,6 +1281,7 @@ func TestDeleteBlobsInUse(t *testing.T) { index.MediaType = ispec.MediaTypeImageIndex var cdigest godigest.Digest + var cblob []byte //nolint: dupl @@ -1294,6 +1320,7 @@ func TestDeleteBlobsInUse(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) _, _, err = imgStore.PutImageManifest(repoName, digest.String(), ispec.MediaTypeImageManifest, content) @@ -1309,6 +1336,7 @@ func TestDeleteBlobsInUse(t *testing.T) { // upload index image indexContent, err := json.Marshal(index) So(err, ShouldBeNil) + indexDigest := godigest.FromBytes(indexContent) So(indexDigest, ShouldNotBeNil) @@ -1396,8 +1424,11 @@ func TestReuploadCorruptedBlob(t *testing.T) { testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var imgStore storageTypes.ImageStore + var testDir, tdir string + var store driver.StorageDriver + var driver storageTypes.Driver log := zlog.Logger{Logger: zerolog.New(os.Stdout)} @@ -1528,16 +1559,24 @@ func TestStorageHandler(t *testing.T) { testcase := testcase t.Run(testcase.testCaseName, func(t *testing.T) { var firstStore storageTypes.ImageStore + var secondStore storageTypes.ImageStore + var thirdStore storageTypes.ImageStore + var firstRootDir string + var secondRootDir string + var thirdRootDir string if testcase.storageType == storageConstants.S3StorageDriverName { tskip.SkipS3(t) + var firstStorageDriver driver.StorageDriver + var secondStorageDriver driver.StorageDriver + var thirdStorageDriver driver.StorageDriver firstRootDir = "/util_test1" @@ -1627,6 +1666,7 @@ func TestGarbageCollectImageManifest(t *testing.T) { Convey("Repo layout", t, func(c C) { Convey("Garbage collect with default/long delay", func() { var imgStore storageTypes.ImageStore + if testcase.storageType == storageConstants.S3StorageDriverName { tskip.SkipS3(t) @@ -1693,6 +1733,7 @@ func TestGarbageCollectImageManifest(t *testing.T) { _, clen, err := imgStore.FullBlobUpload(repoName, bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err := imgStore.CheckBlob(repoName, cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -1716,6 +1757,7 @@ func TestGarbageCollectImageManifest(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err := json.Marshal(manifest) So(err, ShouldBeNil) + digest := godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest(repoName, tag, ispec.MediaTypeImageManifest, manifestBuf) @@ -1883,6 +1925,7 @@ func TestGarbageCollectImageManifest(t *testing.T) { _, clen, err := imgStore.FullBlobUpload(repoName, bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err := imgStore.CheckBlob(repoName, cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -1906,6 +1949,7 @@ func TestGarbageCollectImageManifest(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err := json.Marshal(manifest) So(err, ShouldBeNil) + digest := godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest(repoName, tag, ispec.MediaTypeImageManifest, manifestBuf) @@ -2142,6 +2186,7 @@ func TestGarbageCollectImageManifest(t *testing.T) { _, clen, err := imgStore.FullBlobUpload(repo1Name, bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err := imgStore.CheckBlob(repo1Name, cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -2205,6 +2250,7 @@ func TestGarbageCollectImageManifest(t *testing.T) { _, clen, err = imgStore.FullBlobUpload(repo2Name, bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err = imgStore.CheckBlob(repo2Name, cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -2261,6 +2307,7 @@ func TestGarbageCollectImageManifest(t *testing.T) { _, clen, err = imgStore.FullBlobUpload(repo2Name, bytes.NewReader(cblob), cdigest) So(err, ShouldBeNil) So(clen, ShouldEqual, len(cblob)) + hasBlob, _, err = imgStore.CheckBlob(repo2Name, cdigest) So(err, ShouldBeNil) So(hasBlob, ShouldEqual, true) @@ -2284,6 +2331,7 @@ func TestGarbageCollectImageManifest(t *testing.T) { manifest.SchemaVersion = 2 manifestBuf, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest := godigest.FromBytes(manifestBuf) _, _, err = imgStore.PutImageManifest(repo2Name, tag, ispec.MediaTypeImageManifest, manifestBuf) @@ -2320,6 +2368,7 @@ func TestGarbageCollectImageIndex(t *testing.T) { Convey("Repo layout", t, func(c C) { Convey("Garbage collect with default/long delay", func() { var imgStore storageTypes.ImageStore + if testcase.storageType == storageConstants.S3StorageDriverName { tskip.SkipS3(t) @@ -2821,6 +2870,7 @@ func TestGarbageCollectChainedImageIndexes(t *testing.T) { index.MediaType = ispec.MediaTypeImageIndex var digest godigest.Digest + for i := 0; i < 4; i++ { //nolint: dupl // upload image config blob upload, err := imgStore.NewBlobUpload(repoName) @@ -2856,6 +2906,7 @@ func TestGarbageCollectChainedImageIndexes(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) _, _, err = imgStore.PutImageManifest(repoName, digest.String(), ispec.MediaTypeImageManifest, content) @@ -2938,6 +2989,7 @@ func TestGarbageCollectChainedImageIndexes(t *testing.T) { manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest := godigest.FromBytes(content) So(digest, ShouldNotBeNil) _, _, err = imgStore.PutImageManifest(repoName, digest.String(), ispec.MediaTypeImageManifest, content) @@ -2953,6 +3005,7 @@ func TestGarbageCollectChainedImageIndexes(t *testing.T) { // upload inner index image innerIndexContent, err := json.Marshal(index) So(err, ShouldBeNil) + innerIndexDigest := godigest.FromBytes(innerIndexContent) So(innerIndexDigest, ShouldNotBeNil) @@ -2971,6 +3024,7 @@ func TestGarbageCollectChainedImageIndexes(t *testing.T) { // upload index image indexContent, err := json.Marshal(index) So(err, ShouldBeNil) + indexDigest := godigest.FromBytes(indexContent) So(indexDigest, ShouldNotBeNil) @@ -3241,6 +3295,7 @@ func pushRandomImageIndex(imgStore storageTypes.ImageStore, repoName string, manifest.SchemaVersion = 2 content, err = json.Marshal(manifest) So(err, ShouldBeNil) + digest = godigest.FromBytes(content) So(digest, ShouldNotBeNil) _, _, err = imgStore.PutImageManifest(repoName, digest.String(), ispec.MediaTypeImageManifest, content) @@ -3256,6 +3311,7 @@ func pushRandomImageIndex(imgStore storageTypes.ImageStore, repoName string, // upload index image indexContent, err := json.Marshal(index) So(err, ShouldBeNil) + indexDigest := godigest.FromBytes(indexContent) So(indexDigest, ShouldNotBeNil) diff --git a/pkg/test/auth/bearer.go b/pkg/test/auth/bearer.go index 76ff1e64..f305d5b0 100644 --- a/pkg/test/auth/bearer.go +++ b/pkg/test/auth/bearer.go @@ -43,9 +43,11 @@ func MakeAuthTestServer(serverKey string, unauthorizedNamespace string) *httptes parts := strings.Split(scope, ":") name := parts[1] actions := strings.Split(parts[2], ",") + if name == unauthorizedNamespace { actions = []string{} } + access = []auth.AccessEntry{ { Name: name, @@ -59,6 +61,7 @@ func MakeAuthTestServer(serverKey string, unauthorizedNamespace string) *httptes if err != nil { panic(err) } + response.Header().Set("Content-Type", "application/json") fmt.Fprintf(response, `{"access_token": "%s"}`, token) })) diff --git a/pkg/test/auth/oidc.go b/pkg/test/auth/oidc.go index a3be24f1..f652617e 100644 --- a/pkg/test/auth/oidc.go +++ b/pkg/test/auth/oidc.go @@ -12,7 +12,7 @@ import ( func MockOIDCRun() (*mockoidc.MockOIDC, error) { // Create a fresh RSA Private Key for token signing - rsaKey, _ := rsa.GenerateKey(rand.Reader, 2048) //nolint: gomnd + rsaKey, _ := rsa.GenerateKey(rand.Reader, 2048) //nolint:mnd // Create an unstarted MockOIDC server mockServer, _ := mockoidc.NewServer(rsaKey) @@ -24,7 +24,8 @@ func MockOIDCRun() (*mockoidc.MockOIDC, error) { return http.HandlerFunc(func(response http.ResponseWriter, req *http.Request) { // stateVal := req.Form.Get("state") header := req.Header.Get("Authorization") - parts := strings.SplitN(header, " ", 2) //nolint: gomnd + parts := strings.SplitN(header, " ", 2) //nolint:mnd + if header != "" { if strings.ToLower(parts[0]) == "bearer" { req.Header.Set("Authorization", strings.Join([]string{"Bearer", parts[1]}, " ")) diff --git a/pkg/test/common/fs.go b/pkg/test/common/fs.go index 1cadeaa2..2e7039a4 100644 --- a/pkg/test/common/fs.go +++ b/pkg/test/common/fs.go @@ -145,6 +145,7 @@ func WriteFileWithPermission(path string, data []byte, perm fs.FileMode, overwri if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil { return err } + flag := os.O_WRONLY | os.O_CREATE if overwrite { @@ -230,7 +231,7 @@ func MakeHtpasswdFileFromString(fileContent string) string { } content := []byte(fileContent) - if err := os.WriteFile(htpasswdFile.Name(), content, 0o600); err != nil { //nolint:gomnd + if err := os.WriteFile(htpasswdFile.Name(), content, 0o600); err != nil { //nolint:mnd panic(err) } diff --git a/pkg/test/common/fs_test.go b/pkg/test/common/fs_test.go index 0c1f73ec..256f96e5 100644 --- a/pkg/test/common/fs_test.go +++ b/pkg/test/common/fs_test.go @@ -55,6 +55,7 @@ func TestCopyFiles(t *testing.T) { dir := t.TempDir() filePath := path.Join(dir, "file.txt") + err := os.WriteFile(filePath, []byte("some dummy file content"), 0o644) //nolint: gosec if err != nil { panic(err) @@ -81,12 +82,14 @@ func TestCopyFiles(t *testing.T) { } filePathTrivy := path.Join(srcDir, "_trivy", "db", "trivy.db") + err = os.WriteFile(filePathTrivy, []byte("some dummy file content"), 0o644) //nolint: gosec if err != nil { panic(err) } var index ispec.Index + content, err := json.Marshal(index) if err != nil { panic(err) @@ -220,6 +223,7 @@ func TestCopyTestKeysAndCerts(t *testing.T) { // ----- /test/data doesn't exist ------ workDir, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(workDir) }() dir = t.TempDir() @@ -252,6 +256,7 @@ func TestGetProjectRootDir(t *testing.T) { Convey("GetProjectRootDir negative testing", t, func() { workDir, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(workDir) }() err = os.Chdir(os.TempDir()) @@ -267,9 +272,11 @@ func TestGetCredString(t *testing.T) { Convey("GetCredString panics", t, func() { passwordSize := 100 pass := make([]byte, passwordSize) + for i := 0; i < passwordSize; i++ { pass[i] = 'Y' } + f := func() { tcommon.GetCredString("testUser", string(pass)) } So(f, ShouldPanicWith, bcrypt.ErrPasswordTooLong) }) diff --git a/pkg/test/common/utils.go b/pkg/test/common/utils.go index d2f1d57c..45e62a74 100644 --- a/pkg/test/common/utils.go +++ b/pkg/test/common/utils.go @@ -8,6 +8,7 @@ import ( "net/url" "os" "path" + "strconv" "time" "github.com/phayes/freeport" @@ -139,7 +140,7 @@ func GetFreePort() string { panic(err) } - return fmt.Sprint(port) + return strconv.Itoa(port) } func GetBaseURL(port string) string { diff --git a/pkg/test/image-utils/upload.go b/pkg/test/image-utils/upload.go index dcf1a7d6..c50f1cad 100644 --- a/pkg/test/image-utils/upload.go +++ b/pkg/test/image-utils/upload.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "net/http" + "strconv" godigest "github.com/opencontainers/go-digest" ispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -42,12 +43,11 @@ func UploadImage(img Image, baseURL, repo, ref string) error { digest := digestAlgorithm.FromBytes(blob).String() resp, err = resty.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). Put(baseURL + loc) - if err != nil { return err } @@ -91,7 +91,7 @@ func UploadImage(img Image, baseURL, repo, ref string) error { // uploading blob should get 201 resp, err = resty.R(). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). @@ -151,12 +151,11 @@ func UploadImageWithBasicAuth(img Image, baseURL, repo, ref, user, password stri resp, err = resty.R(). SetBasicAuth(user, password). - SetHeader("Content-Length", fmt.Sprintf("%d", len(blob))). + SetHeader("Content-Length", strconv.Itoa(len(blob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", digest). SetBody(blob). Put(baseURL + loc) - if err != nil { return err } @@ -194,7 +193,7 @@ func UploadImageWithBasicAuth(img Image, baseURL, repo, ref, user, password stri // uploading blob should get 201 resp, err = resty.R(). SetBasicAuth(user, password). - SetHeader("Content-Length", fmt.Sprintf("%d", len(cblob))). + SetHeader("Content-Length", strconv.Itoa(len(cblob))). SetHeader("Content-Type", "application/octet-stream"). SetQueryParam("digest", cdigest.String()). SetBody(cblob). diff --git a/pkg/test/image-utils/upload_test.go b/pkg/test/image-utils/upload_test.go index 07e94b97..e7ae8eee 100644 --- a/pkg/test/image-utils/upload_test.go +++ b/pkg/test/image-utils/upload_test.go @@ -179,6 +179,7 @@ func TestUploadImage(t *testing.T) { user1 := "test" password1 := "test" testString1 := tcommon.GetCredString(user1, password1) + htpasswdPath := tcommon.MakeHtpasswdFileFromString(testString1) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ @@ -266,6 +267,7 @@ func TestUploadImage(t *testing.T) { if err != nil { t.Fatal(err) } + file, err := os.Create(path.Join(layerPath, layerBlobDigest.Encoded())) if err != nil { t.Fatal(err) @@ -275,11 +277,13 @@ func TestUploadImage(t *testing.T) { if err != nil { t.Fatal(err) } + defer func() { err = os.Chmod(layerPath, 0o700) if err != nil { t.Fatal(err) } + os.RemoveAll(file.Name()) }() } @@ -492,6 +496,7 @@ func TestInjectUploadImageWithBasicAuth(t *testing.T) { user := "user" password := "password" testString := tcommon.GetCredString(user, password) + htpasswdPath := tcommon.MakeHtpasswdFileFromString(testString) defer os.Remove(htpasswdPath) conf.HTTP.Auth = &config.AuthConfig{ diff --git a/pkg/test/image-utils/utils.go b/pkg/test/image-utils/utils.go index f4484937..58018011 100644 --- a/pkg/test/image-utils/utils.go +++ b/pkg/test/image-utils/utils.go @@ -112,12 +112,12 @@ func DateRef(year int, month time.Month, day, hour, min, sec, nsec int, loc *tim func RandomDateRef(loc *time.Location) *time.Time { var ( - year = 1990 + mathRand.Intn(30) //nolint: gosec,gomnd - month = time.Month(1 + mathRand.Intn(10)) //nolint: gosec,gomnd - day = 1 + mathRand.Intn(5) //nolint: gosec,gomnd - hour = 1 + mathRand.Intn(22) //nolint: gosec,gomnd - min = 1 + mathRand.Intn(58) //nolint: gosec,gomnd - sec = 1 + mathRand.Intn(58) //nolint: gosec,gomnd + year = 1990 + mathRand.Intn(30) //nolint: gosec,mnd + month = time.Month(1 + mathRand.Intn(10)) //nolint: gosec,mnd + day = 1 + mathRand.Intn(5) //nolint: gosec,mnd + hour = 1 + mathRand.Intn(22) //nolint: gosec,mnd + min = 1 + mathRand.Intn(58) //nolint: gosec,mnd + sec = 1 + mathRand.Intn(58) //nolint: gosec,mnd nsec = 1 ) diff --git a/pkg/test/mocks/repo_db_mock.go b/pkg/test/mocks/repo_db_mock.go index 73d3035a..53ca5f2a 100644 --- a/pkg/test/mocks/repo_db_mock.go +++ b/pkg/test/mocks/repo_db_mock.go @@ -252,7 +252,7 @@ func (sdm MetaDBMock) GetUserAPIKeys(ctx context.Context) ([]mTypes.APIKeyDetail return sdm.GetUserAPIKeysFn(ctx) } - return nil, nil + return nil, nil //nolint:nilnil } func (sdm MetaDBMock) AddUserAPIKey(ctx context.Context, hashedKey string, apiKeyDetails *mTypes.APIKeyDetails) error { diff --git a/pkg/test/mocks/sync_remote_mock.go b/pkg/test/mocks/sync_remote_mock.go index 9c7e418b..c22d74fd 100644 --- a/pkg/test/mocks/sync_remote_mock.go +++ b/pkg/test/mocks/sync_remote_mock.go @@ -39,7 +39,7 @@ func (remote SyncRemote) GetImageReference(repo string, tag string) (types.Image return remote.GetImageReferenceFn(repo, tag) } - return nil, nil + return nil, nil //nolint:nilnil } func (remote SyncRemote) GetContext() *types.SystemContext { diff --git a/pkg/test/oci-utils/oci_layout.go b/pkg/test/oci-utils/oci_layout.go index d217760e..f2a1cc54 100644 --- a/pkg/test/oci-utils/oci_layout.go +++ b/pkg/test/oci-utils/oci_layout.go @@ -407,7 +407,7 @@ func (olu BaseOciLayoutUtils) GetExpandedRepoInfo(repoName string) (common.RepoI isSigned := olu.CheckManifestSignature(repoName, man.Digest) manifestSize := olu.GetImageManifestSize(repoName, man.Digest) - olu.Log.Debug().Msg(fmt.Sprintf("%v", man.Digest.String())) + olu.Log.Debug().Msg(man.Digest.String()) configSize := manifest.Config.Size repoBlob2Size[man.Digest.String()] = manifestSize diff --git a/pkg/test/oci-utils/oci_layout_test.go b/pkg/test/oci-utils/oci_layout_test.go index cb63dc8d..75908bfc 100644 --- a/pkg/test/oci-utils/oci_layout_test.go +++ b/pkg/test/oci-utils/oci_layout_test.go @@ -5,6 +5,7 @@ package ociutils_test import ( "encoding/json" + "errors" "fmt" "os" "path" @@ -28,10 +29,10 @@ import ( . "zotregistry.dev/zot/pkg/test/image-utils" "zotregistry.dev/zot/pkg/test/mocks" ociutils "zotregistry.dev/zot/pkg/test/oci-utils" - signature "zotregistry.dev/zot/pkg/test/signature" + "zotregistry.dev/zot/pkg/test/signature" ) -var ErrTestError = fmt.Errorf("testError") +var ErrTestError = errors.New("testError") func TestBaseOciLayoutUtils(t *testing.T) { Convey("GetImageManifestSize fail", t, func() { diff --git a/pkg/test/oci-utils/repo_test.go b/pkg/test/oci-utils/repo_test.go index 97b9848e..69aadda0 100644 --- a/pkg/test/oci-utils/repo_test.go +++ b/pkg/test/oci-utils/repo_test.go @@ -2,7 +2,7 @@ package ociutils_test import ( "context" - "fmt" + "errors" "testing" . "github.com/smartystreets/goconvey/convey" @@ -13,7 +13,7 @@ import ( ociutils "zotregistry.dev/zot/pkg/test/oci-utils" ) -var ErrTestFail = fmt.Errorf("fail") +var ErrTestFail = errors.New("fail") func TestInitializeMetaDBErrors(t *testing.T) { ctx := context.Background() diff --git a/pkg/test/signature/notation.go b/pkg/test/signature/notation.go index 9a379cb3..b96e7b2f 100644 --- a/pkg/test/signature/notation.go +++ b/pkg/test/signature/notation.go @@ -84,12 +84,12 @@ func GenerateNotationCerts(tdir string, certName string) error { return err } - if err := tcommon.WriteFileWithPermission(keyPath, keyPEM, 0o600, false); err != nil { //nolint:gomnd + if err := tcommon.WriteFileWithPermission(keyPath, keyPEM, 0o600, false); err != nil { //nolint:mnd return fmt.Errorf("failed to write key file: %w", err) } // write self-signed certificate - if err := tcommon.WriteFileWithPermission(certPath, certBytes, 0o644, false); err != nil { //nolint:gomnd + if err := tcommon.WriteFileWithPermission(certPath, certBytes, 0o644, false); err != nil { //nolint:mnd return fmt.Errorf("failed to write certificate file: %w", err) } @@ -114,13 +114,13 @@ func GenerateNotationCerts(tdir string, certName string) error { signingKeys.Keys = append(signingKeys.Keys, keySuite) // Add to the trust store - trustStorePath := path.Join(tdir, fmt.Sprintf("notation/truststore/x509/ca/%s", certName)) + trustStorePath := path.Join(tdir, "notation/truststore/x509/ca/"+certName) if _, err := os.Stat(filepath.Join(trustStorePath, filepath.Base(certPath))); err == nil { return ErrAlreadyExists } - if err := os.MkdirAll(trustStorePath, 0o755); err != nil { //nolint:gomnd + if err := os.MkdirAll(trustStorePath, 0o755); err != nil { //nolint:mnd return fmt.Errorf("GenerateNotationCerts os.MkdirAll failed: %w", err) } diff --git a/pkg/test/signature/notation_test.go b/pkg/test/signature/notation_test.go index 57b7d685..f8e29e36 100644 --- a/pkg/test/signature/notation_test.go +++ b/pkg/test/signature/notation_test.go @@ -17,7 +17,7 @@ import ( "zotregistry.dev/zot/pkg/api/config" tcommon "zotregistry.dev/zot/pkg/test/common" . "zotregistry.dev/zot/pkg/test/image-utils" - signature "zotregistry.dev/zot/pkg/test/signature" + "zotregistry.dev/zot/pkg/test/signature" ) func TestLoadNotationSigningkeys(t *testing.T) { @@ -135,7 +135,9 @@ func TestSignWithNotation(t *testing.T) { Convey("not enough permissions to access notation/localkeys dir", t, func() { cwd, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(cwd) }() + tdir := t.TempDir() _ = os.Chdir(tdir) @@ -160,7 +162,9 @@ func TestSignWithNotation(t *testing.T) { Convey("error parsing reference", t, func() { cwd, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(cwd) }() + tdir := t.TempDir() _ = os.Chdir(tdir) @@ -179,7 +183,9 @@ func TestSignWithNotation(t *testing.T) { Convey("error signing", t, func() { cwd, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(cwd) }() + tdir := t.TempDir() _ = os.Chdir(tdir) @@ -205,7 +211,9 @@ func TestVerifyWithNotation(t *testing.T) { Convey("error parsing reference", t, func() { cwd, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(cwd) }() + tdir := t.TempDir() _ = os.Chdir(tdir) @@ -224,7 +232,9 @@ func TestVerifyWithNotation(t *testing.T) { Convey("error trying to get manifest", t, func() { cwd, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(cwd) }() + tdir := t.TempDir() _ = os.Chdir(tdir) @@ -287,7 +297,9 @@ func TestListNotarySignatures(t *testing.T) { Convey("error parsing reference", t, func() { cwd, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(cwd) }() + tdir := t.TempDir() _ = os.Chdir(tdir) @@ -298,7 +310,9 @@ func TestListNotarySignatures(t *testing.T) { Convey("error trying to get manifest", t, func() { cwd, err := os.Getwd() So(err, ShouldBeNil) + defer func() { _ = os.Chdir(cwd) }() + tdir := t.TempDir() _ = os.Chdir(tdir) @@ -427,7 +441,7 @@ func TestGenerateNotationCerts(t *testing.T) { So(err, ShouldBeNil) certName := "cert-test" - trustStorePath := path.Join(notationDir, fmt.Sprintf("truststore/x509/ca/%s", certName)) + trustStorePath := path.Join(notationDir, "truststore/x509/ca/"+certName) err = os.MkdirAll(trustStorePath, 0o755) So(err, ShouldBeNil) err = os.Chmod(path.Join(notationDir, "truststore/x509"), 0o000) diff --git a/pkg/test/skip/skip_test.go b/pkg/test/skip/skip_test.go index 0aba04cb..ba24c2fc 100644 --- a/pkg/test/skip/skip_test.go +++ b/pkg/test/skip/skip_test.go @@ -4,7 +4,7 @@ import ( "os" "testing" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" tskip "zotregistry.dev/zot/pkg/test/skip" ) @@ -17,7 +17,7 @@ func TestSkipS3(t *testing.T) { if len(envVal) > 0 { defer os.Setenv(envName, envVal) err := os.Unsetenv(envName) - assert.Equal(t, err, nil, "Error should be nil") + require.NoError(t, err, "Error should be nil") } tskip.SkipS3(t) @@ -30,7 +30,7 @@ func TestSkipDynamo(t *testing.T) { if len(envVal) > 0 { defer os.Setenv(envName, envVal) err := os.Unsetenv(envName) - assert.Equal(t, err, nil, "Error should be nil") + require.NoError(t, err, "Error should be nil") } tskip.SkipDynamo(t)