diff --git a/Makefile b/Makefile index e70c857c..8d5cdfcc 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ NOTATION := $(TOOLSDIR)/bin/notation COSIGN := $(TOOLSDIR)/bin/cosign HELM := $(TOOLSDIR)/bin/helm ORAS := $(TOOLSDIR)/bin/oras +ORAS_VERSION := 0.16.0 REGCLIENT := $(TOOLSDIR)/bin/regctl REGCLIENT_VERSION := v0.4.5 STACKER := $(TOOLSDIR)/bin/stacker @@ -110,7 +111,7 @@ $(NOTATION): $(ORAS): mkdir -p $(TOOLSDIR)/bin - curl -Lo oras.tar.gz https://github.com/oras-project/oras/releases/download/v0.14.0/oras_0.14.0_linux_amd64.tar.gz + curl -Lo oras.tar.gz https://github.com/oras-project/oras/releases/download/v$(ORAS_VERSION)/oras_$(ORAS_VERSION)_linux_amd64.tar.gz tar xvzf oras.tar.gz -C $(TOOLSDIR)/bin oras rm oras.tar.gz diff --git a/pkg/api/controller_test.go b/pkg/api/controller_test.go index ea70a40e..16f550b5 100644 --- a/pkg/api/controller_test.go +++ b/pkg/api/controller_test.go @@ -4310,7 +4310,12 @@ func TestArtifactReferences(t *testing.T) { Convey("Validate Image Manifest Reference", func() { resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) So(err, ShouldBeNil) - So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + + var referrers ispec.Index + err := json.Unmarshal(resp.Body(), &referrers) + So(err, ShouldBeNil) + So(referrers.Manifests, ShouldBeEmpty) // now upload a reference @@ -4362,14 +4367,19 @@ func TestArtifactReferences(t *testing.T) { So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) - resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) + // unknown repo will return status not found + resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", "unknown", digest.String())) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) + So(err, ShouldBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + resp, err = resty.R().SetQueryParams(map[string]string{"artifactType": artifactType}). Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) So(err, ShouldBeNil) - So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) Convey("Using valid content", func() { content, err = json.Marshal(manifest) @@ -4391,7 +4401,7 @@ func TestArtifactReferences(t *testing.T) { resp, err = resty.R().SetQueryParams(map[string]string{"artifactType": "invalid"}). Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) So(err, ShouldBeNil) - So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) resp, err = resty.R().SetQueryParams(map[string]string{"artifactType": artifactType}). Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) @@ -4404,7 +4414,12 @@ func TestArtifactReferences(t *testing.T) { Convey("Validate Artifact Manifest Reference", func() { resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) So(err, ShouldBeNil) - So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + + var referrers ispec.Index + err := json.Unmarshal(resp.Body(), &referrers) + So(err, ShouldBeNil) + So(referrers.Manifests, ShouldBeEmpty) // now upload a reference @@ -4455,14 +4470,19 @@ func TestArtifactReferences(t *testing.T) { So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusBadRequest) - resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) + // unknown repo will return status not found + resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", "unknown", digest.String())) So(err, ShouldBeNil) So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + resp, err = resty.R().Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) + So(err, ShouldBeNil) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) + resp, err = resty.R().SetQueryParams(map[string]string{"artifactType": artifactType}). Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) So(err, ShouldBeNil) - So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) }) Convey("Using valid content", func() { content, err = json.Marshal(manifest) @@ -4486,7 +4506,7 @@ func TestArtifactReferences(t *testing.T) { resp, err = resty.R().SetQueryParams(map[string]string{"artifactType": "invalid"}). Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) So(err, ShouldBeNil) - So(resp.StatusCode(), ShouldEqual, http.StatusNotFound) + So(resp.StatusCode(), ShouldEqual, http.StatusOK) resp, err = resty.R().SetQueryParams(map[string]string{"artifactType": artifactType}). Get(baseURL + fmt.Sprintf("/v2/%s/referrers/%s", repoName, digest.String())) diff --git a/pkg/api/routes.go b/pkg/api/routes.go index 83749662..f7b253cb 100644 --- a/pkg/api/routes.go +++ b/pkg/api/routes.go @@ -489,8 +489,13 @@ func (rh *RouteHandler) GetReferrers(response http.ResponseWriter, request *http referrers, err := getReferrers(request.Context(), rh, imgStore, name, digest, artifactType) if err != nil { + if errors.Is(err, zerr.ErrManifestNotFound) || errors.Is(err, zerr.ErrRepoNotFound) { + rh.c.Log.Error().Err(err).Str("name", name).Str("digest", digest.String()).Msg("manifest not found") + response.WriteHeader(http.StatusNotFound) + } + rh.c.Log.Error().Err(err).Str("name", name).Str("digest", digest.String()).Msg("unable to get references") - response.WriteHeader(http.StatusNotFound) + response.WriteHeader(http.StatusInternalServerError) return } diff --git a/pkg/storage/common.go b/pkg/storage/common.go index 03aa687d..a87d6e73 100644 --- a/pkg/storage/common.go +++ b/pkg/storage/common.go @@ -548,8 +548,6 @@ func GetReferrers(imgStore ImageStore, repo string, gdigest godigest.Digest, art return nilIndex, err } - found := false - result := []ispec.Descriptor{} for _, manifest := range index.Manifests { @@ -617,12 +615,6 @@ func GetReferrers(imgStore ImageStore, repo string, gdigest godigest.Digest, art Annotations: art.Annotations, }) } - - found = true - } - - if !found { - return nilIndex, zerr.ErrManifestNotFound } index = ispec.Index{ diff --git a/pkg/storage/common_test.go b/pkg/storage/common_test.go index c9e3a05f..846ab542 100644 --- a/pkg/storage/common_test.go +++ b/pkg/storage/common_test.go @@ -299,7 +299,7 @@ func TestGetReferrersErrors(t *testing.T) { } _, err = storage.GetReferrers(imgStore, "zot-test", validDigest, artifactType, log.With().Caller().Logger()) - So(err, ShouldNotBeNil) + So(err, ShouldBeNil) }) }) } diff --git a/test/blackbox/pushpull.bats b/test/blackbox/pushpull.bats index 27741723..e196dd37 100644 --- a/test/blackbox/pushpull.bats +++ b/test/blackbox/pushpull.bats @@ -63,8 +63,6 @@ function teardown_file() { run cat ${BATS_FILE_TMPDIR}/oci/golang/index.json [ "$status" -eq 0 ] [ $(echo "${lines[-1]}" | jq '.manifests[].annotations."org.opencontainers.image.ref.name"') = '"1.19"' ] - run curl -X DELETE http://127.0.0.1:8080/v2/golang/manifests/1.19 - [ "$status" -eq 0 ] } @test "push image index" { @@ -119,6 +117,23 @@ function teardown_file() { rm -f artifact.txt } +@test "attach oras artifacts" { + # attach signature + echo "{\"artifact\": \"\", \"signature\": \"pat hancock\"}" > signature.json + run oras attach --plain-http 127.0.0.1:8080/golang:1.19 --artifact-type 'signature/example' ./signature.json:application/json + [ "$status" -eq 0 ] + # attach sbom + echo "{\"version\": \"0.0.0.0\", \"artifact\": \"'127.0.0.1:8080/golang:1.19'\", \"contents\": \"good\"}" > sbom.json + run oras attach --plain-http 127.0.0.1:8080/golang:1.19 --artifact-type 'sbom/example' ./sbom.json:application/json + [ "$status" -eq 0 ] +} + +@test "discover oras artifacts" { + run oras discover --plain-http -o json 127.0.0.1:8080/golang:1.19 + [ "$status" -eq 0 ] + [ $(echo "$output" | jq -r ".manifests | length") -eq 2 ] +} + @test "push helm chart" { run helm package ${BATS_FILE_TMPDIR}/helm-charts/charts/zot [ "$status" -eq 0 ]