Skip to content

Commit

Permalink
feat!: implement the referrers route in the v2 package (#32)
Browse files Browse the repository at this point in the history
Implement the `referrers` route in the `registry/api/v2` package. Path
with filtering on `ArtifactType` is also implemented. Unit tests are
included. The next pr will implement `referrersHandler` but probably
will not implement filtering yet.

Part 5 of #21 

Signed-off-by: wangxiaoxuan273 <[email protected]>
  • Loading branch information
wangxiaoxuan273 authored Nov 4, 2022
1 parent 0e64ff7 commit 6f0e3ea
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 0 deletions.
128 changes: 128 additions & 0 deletions registry/api/v2/descriptors.go
Original file line number Diff line number Diff line change
Expand Up @@ -1595,6 +1595,134 @@ var routeDescriptors = []RouteDescriptor{
},
},
},
{
Name: RouteNameReferrers,
Path: "/v2/{name:" + reference.NameRegexp.String() + "}/referrers/{digest:" + digest.DigestRegexp.String() + "}",
Entity: "Referrers",
Description: `Retrieve information about referrers.`,
Methods: []MethodDescriptor{
{
Method: "GET",
Description: "Fetch the referrers of the artifact identified by `digest`.",
Requests: []RequestDescriptor{
{
Name: "Referrers",
Description: "Request an unabridged list of referrers.",
Successes: []ResponseDescriptor{
{
Description: "Returns an image index containing all referrers as a json response.",
StatusCode: http.StatusOK,
Headers: []ParameterDescriptor{
{
Name: "Content-Length",
Type: "integer",
Description: "Length of the JSON response body.",
Format: "<length>",
},
linkHeader,
},
Body: BodyDescriptor{
ContentType: "application/vnd.oci.image.index.v1+json",
Format: `{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
<manifest>,
...
]
}`,
},
},
},
Failures: []ResponseDescriptor{
{
Description: "The registry does not support referrers API.",
StatusCode: http.StatusNotFound,
},
{
Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `digest`.",
StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{
ErrorCodeDigestInvalid,
},
Body: BodyDescriptor{
ContentType: "application/json",
Format: errorsBody,
},
},
deniedResponseDescriptor,
tooManyRequestsDescriptor,
},
},
{
// may need to change to accommodate multiple filters applied.
// spec is not clear regarding applying multiple filters
Name: "referrers with filtering",
Description: "Request a list of referrers filtered on artifact type.",
QueryParameters: []ParameterDescriptor{
{
Name: "artifactType",
Type: "string",
Description: "This is the artifact type to be appied on the filter.",
Format: "<string>",
Required: false,
},
},
Successes: []ResponseDescriptor{
{
Description: "Returns an image index containing all referrers as a json response with the filter applied.",
StatusCode: http.StatusOK,
Headers: []ParameterDescriptor{
{
Name: "Content-Length",
Type: "integer",
Description: "Length of the JSON response body.",
Format: "<length>",
},
linkHeader,
},
Body: BodyDescriptor{
ContentType: "application/vnd.oci.image.index.v1+json",
Format: `{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json",
"manifests": [
<manifest>,
...
],
"annotations": {
"org.opencontainers.referrers.filtersApplied": <filter>,
...
}
}`,
},
},
},
Failures: []ResponseDescriptor{
{
Description: "The registry does not support referrers API.",
StatusCode: http.StatusNotFound,
},
{
Description: "There was a problem with the request that needs to be addressed by the client, such as an invalid `name` or `digest`.",
StatusCode: http.StatusBadRequest,
ErrorCodes: []errcode.ErrorCode{
ErrorCodeDigestInvalid,
},
Body: BodyDescriptor{
ContentType: "application/json",
Format: errorsBody,
},
},
repositoryNotFoundResponseDescriptor,
deniedResponseDescriptor,
tooManyRequestsDescriptor,
},
},
},
},
},
},
}

var routeDescriptorsMap map[string]RouteDescriptor
Expand Down
1 change: 1 addition & 0 deletions registry/api/v2/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const (
RouteNameBlobUpload = "blob-upload"
RouteNameBlobUploadChunk = "blob-upload-chunk"
RouteNameCatalog = "catalog"
RouteNameReferrers = "referrers"
)

var (
Expand Down
8 changes: 8 additions & 0 deletions registry/api/v2/routes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ func TestRouter(t *testing.T) {
"reference": "tag",
},
},
{
RouteName: RouteNameReferrers,
RequestURI: "/v2/foo/referrers/sha256:abcdef0919234",
Vars: map[string]string{
"name": "foo",
"digest": "sha256:abcdef0919234",
},
},
}

checkTestRouter(t, testCases, "", true)
Expand Down
12 changes: 12 additions & 0 deletions registry/api/v2/urls.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,18 @@ func (ub *URLBuilder) BuildManifestURL(ref reference.Named) (string, error) {
return manifestURL.String(), nil
}

// BuildReferrersURL constructs the url to fetch a list of referrers
func (ub *URLBuilder) BuildReferrersURL(ref reference.Canonical, values ...url.Values) (string, error) {
route := ub.cloneRoute(RouteNameReferrers)

referrersURL, err := route.URL("name", ref.Name(), "digest", ref.Digest().String())
if err != nil {
return "", err
}

return appendValuesURL(referrersURL, values...).String(), nil
}

// BuildBlobURL constructs the url for the blob identified by name and dgst.
func (ub *URLBuilder) BuildBlobURL(ref reference.Canonical) (string, error) {
route := ub.cloneRoute(RouteNameBlob)
Expand Down
20 changes: 20 additions & 0 deletions registry/api/v2/urls_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,26 @@ func makeURLBuilderTestCases(urlBuilder *URLBuilder) []urlBuilderTestCase {
})
},
},
{
description: "build referrers url",
expectedPath: "/v2/foo/bar/referrers/sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5",
expectedErr: nil,
build: func() (string, error) {
ref, _ := reference.WithDigest(fooBarRef, "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5")
return urlBuilder.BuildReferrersURL(ref)
},
},
{
description: "build referrers url with artifact type parameter",
expectedPath: "/v2/foo/bar/referrers/sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5?artifactType=example.test.type",
expectedErr: nil,
build: func() (string, error) {
ref, _ := reference.WithDigest(fooBarRef, "sha256:3b3692957d439ac1928219a83fac91e7bf96c153725526874673ae1f2023f8d5")
return urlBuilder.BuildReferrersURL(ref, url.Values{
"artifactType": []string{"example.test.type"},
})
},
},
}
}

Expand Down

0 comments on commit 6f0e3ea

Please sign in to comment.