diff --git a/docs/spec/api.md b/docs/spec/api.md index c573178a..9b56b6c5 100644 --- a/docs/spec/api.md +++ b/docs/spec/api.md @@ -175,7 +175,6 @@ identify a set of modifications.
  • Added error code for unsupported operations.
  • - ## Overview @@ -727,7 +726,8 @@ delete may be issued with the following request format: DELETE /v2//blobs/ -If the blob exists and has been successfully deleted, the following response will be issued: +If the blob exists and has been successfully deleted, the following response +will be issued: 202 Accepted Content-Length: None @@ -735,6 +735,8 @@ If the blob exists and has been successfully deleted, the following response wil If the blob had already been deleted or did not exist, a `404 Not Found` response will be issued instead. +If a layer is deleted which is referenced by a manifest in the registry, +then the complete images will not be resolvable. #### Pushing an Image Manifest @@ -1016,13 +1018,13 @@ A list of methods and URIs are covered in the table below: | PUT | `/v2//manifests/` | Manifest | Put the manifest identified by `name` and `reference` where `reference` can be a tag or digest. | | DELETE | `/v2//manifests/` | Manifest | Delete the manifest identified by `name` and `reference`. Note that a manifest can _only_ be deleted by `digest`. | | GET | `/v2//blobs/` | Blob | Retrieve the blob from the registry identified by `digest`. A `HEAD` request can also be issued to this endpoint to obtain resource information without receiving all data. | +| DELETE | `/v2//blobs/` | Blob | Delete the blob identified by `name` and `digest` | | POST | `/v2//blobs/uploads/` | Initiate Blob Upload | Initiate a resumable blob upload. If successful, an upload location will be provided to complete the upload. Optionally, if the `digest` parameter is present, the request body will be used to complete the upload in a single request. | | GET | `/v2//blobs/uploads/` | Blob Upload | Retrieve status of upload identified by `uuid`. The primary purpose of this endpoint is to resolve the current status of a resumable upload. | | PATCH | `/v2//blobs/uploads/` | Blob Upload | Upload a chunk of data for the specified upload. | | PUT | `/v2//blobs/uploads/` | Blob Upload | Complete the upload specified by `uuid`, optionally appending the body as the final chunk. | | DELETE | `/v2//blobs/uploads/` | Blob Upload | Cancel outstanding upload processes, releasing associated resources. If this is not called, the unfinished uploads will eventually timeout. | | GET | `/v2/_catalog` | Catalog | Retrieve a sorted, json list of repositories available in the registry. | -| DELETE | `/v2//blobs/` | Blob delete | Delete the blob identified by `name` and `digest`| The detail for each endpoint is covered in the following sections. @@ -1374,7 +1376,7 @@ The error codes that may be included in the response body are enumerated below: ### Manifest -Create, update and retrieve manifests. +Create, update, delete and retrieve manifests. @@ -1732,7 +1734,6 @@ The error codes that may be included in the response body are enumerated below: #### DELETE Manifest - Delete the manifest identified by `name` and `reference`. Note that a manifest can _only_ be deleted by `digest`. @@ -1874,7 +1875,7 @@ The error codes that may be included in the response body are enumerated below: ### Blob -Fetch the blob identified by `name` and `digest`. Used to fetch layers by digest. +Operations on blobs identified by `name` and `digest`. Used to fetch or delete layers by digest. @@ -2207,6 +2208,134 @@ The range specification cannot be satisfied for the requested content. This can +#### DELETE Blob + +Delete the blob identified by `name` and `digest` + + + +``` +DELETE /v2//blobs/ +Host: +Authorization: +``` + + + + +The following parameters should be specified on the request: + +|Name|Kind|Description| +|----|----|-----------| +|`Host`|header|Standard HTTP Host Header. Should be set to the registry host.| +|`Authorization`|header|An RFC7235 compliant authorization header.| +|`name`|path|Name of the target repository.| +|`digest`|path|Digest of desired blob.| + + + + +###### On Success: Accepted + +``` +202 Accepted +Content-Length: 0 +Docker-Content-Digest: +``` + + + +The following headers will be returned with the response: + +|Name|Description| +|----|-----------| +|`Content-Length`|Zero| +|`Docker-Content-Digest`|Digest of the targeted content for the request.| + + + + +###### On Failure: Invalid Name or Digest + +``` +400 Bad Request +``` + + + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +|----|-------|-----------| +| `DIGEST_INVALID` | provided digest did not match uploaded content | When a blob is uploaded, the registry will check that the content matches the digest provided by the client. The error may include a detail structure with the key "digest", including the invalid digest string. This error may also be returned when a manifest includes an invalid layer digest. | +| `NAME_INVALID` | invalid repository name | Invalid repository name encountered either during manifest validation or any API operation. | + + + +###### On Failure: Not Found + +``` +404 Not Found +Content-Type: application/json; charset=utf-8 + +{ + "errors:" [ + { + "code": , + "message": "", + "detail": ... + }, + ... + ] +} +``` + +The blob, identified by `name` and `digest`, is unknown to the registry. + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +|----|-------|-----------| +| `NAME_UNKNOWN` | repository name not known to registry | This is returned if the name used during an operation is unknown to the registry. | +| `BLOB_UNKNOWN` | blob unknown to registry | This error may be returned when a blob is unknown to the registry in a specified repository. This can be returned with a standard get or if a manifest references an unknown layer during upload. | + + + +###### On Failure: Method Not Allowed + +``` +405 Method Not Allowed +Content-Type: application/json; charset=utf-8 + +{ + "errors:" [ + { + "code": , + "message": "", + "detail": ... + }, + ... + ] +} +``` + +Delete is not enabled on the registry + + + +The error codes that may be included in the response body are enumerated below: + +|Code|Message|Description| +|----|-------|-----------| +| `UNSUPPORTED` | The operation is unsupported. | The operation was unsupported due to a missing implementation or invalid set of parameters. | + + + + ### Initiate Blob Upload diff --git a/docs/spec/api.md.tmpl b/docs/spec/api.md.tmpl index de2f5a90..cc6bd7c5 100644 --- a/docs/spec/api.md.tmpl +++ b/docs/spec/api.md.tmpl @@ -277,7 +277,7 @@ API. When this header is omitted, clients may fallback to an older API version. This API design is driven heavily by [content addressability](http://en.wikipedia.org/wiki/Content-addressable_storage). The core of this design is the concept of a content addressable identifier. It -uniquely identifies content by taking a collision-resistent hash of the bytes. +uniquely identifies content by taking a collision-resistant hash of the bytes. Such an identifier can be independently calculated and verified by selection of a common _algorithm_. If such an identifier can be communicated in a secure manner, one can retrieve the content from an insecure source, calculate it @@ -791,7 +791,7 @@ Images are stored in collections, known as a _repository_, which is keyed by a contain several repositories. The list of available repositories is made available through the _catalog_. -The catalog for a given registry can be retrived with the following request: +The catalog for a given registry can be retrieved with the following request: ``` GET /v2/_catalog @@ -875,7 +875,7 @@ To get the next result set, a client would issue the request as follows, using the URL encoded in the described `Link` header: ``` -GET /v2/_catalog?n=&last= +GET /v2/_catalog?n=&last= ``` The above process should then be repeated until the `Link` header is no longer diff --git a/registry/api/v2/descriptors.go b/registry/api/v2/descriptors.go index 74bdb9f2..0ef64f88 100644 --- a/registry/api/v2/descriptors.go +++ b/registry/api/v2/descriptors.go @@ -519,7 +519,7 @@ var routeDescriptors = []RouteDescriptor{ Name: RouteNameManifest, Path: "/v2/{name:" + RepositoryNameRegexp.String() + "}/manifests/{reference:" + TagNameRegexp.String() + "|" + digest.DigestRegexp.String() + "}", Entity: "Manifest", - Description: "Create, update and retrieve manifests.", + Description: "Create, update, delete and retrieve manifests.", Methods: []MethodDescriptor{ { Method: "GET", @@ -536,7 +536,7 @@ var routeDescriptors = []RouteDescriptor{ }, Successes: []ResponseDescriptor{ { - Description: "The manifest idenfied by `name` and `reference`. The contents can be used to identify and resolve resources required to run the specified image.", + Description: "The manifest identified by `name` and `reference`. The contents can be used to identify and resolve resources required to run the specified image.", StatusCode: http.StatusOK, Headers: []ParameterDescriptor{ digestHeader, @@ -768,9 +768,8 @@ var routeDescriptors = []RouteDescriptor{ Name: RouteNameBlob, Path: "/v2/{name:" + RepositoryNameRegexp.String() + "}/blobs/{digest:" + digest.DigestRegexp.String() + "}", Entity: "Blob", - Description: "Fetch the blob identified by `name` and `digest`. Used to fetch layers by digest.", + Description: "Operations on blobs identified by `name` and `digest`. Used to fetch or delete layers by digest.", Methods: []MethodDescriptor{ - { Method: "GET", Description: "Retrieve the blob from the registry identified by `digest`. A `HEAD` request can also be issued to this endpoint to obtain resource information without receiving all data.", @@ -919,6 +918,70 @@ var routeDescriptors = []RouteDescriptor{ }, }, }, + { + Method: "DELETE", + Description: "Delete the blob identified by `name` and `digest`", + Requests: []RequestDescriptor{ + { + Headers: []ParameterDescriptor{ + hostHeader, + authHeader, + }, + PathParameters: []ParameterDescriptor{ + nameParameterDescriptor, + digestPathParameter, + }, + Successes: []ResponseDescriptor{ + { + StatusCode: http.StatusAccepted, + Headers: []ParameterDescriptor{ + { + Name: "Content-Length", + Type: "integer", + Description: "0", + Format: "0", + }, + digestHeader, + }, + }, + }, + Failures: []ResponseDescriptor{ + { + Name: "Invalid Name or Digest", + StatusCode: http.StatusBadRequest, + ErrorCodes: []errcode.ErrorCode{ + ErrorCodeDigestInvalid, + ErrorCodeNameInvalid, + }, + }, + { + Description: "The blob, identified by `name` and `digest`, is unknown to the registry.", + StatusCode: http.StatusNotFound, + Body: BodyDescriptor{ + ContentType: "application/json; charset=utf-8", + Format: errorsBody, + }, + ErrorCodes: []errcode.ErrorCode{ + ErrorCodeNameUnknown, + ErrorCodeBlobUnknown, + }, + }, + { + Description: "Delete is not enabled on the registry", + StatusCode: http.StatusMethodNotAllowed, + Body: BodyDescriptor{ + ContentType: "application/json; charset=utf-8", + Format: errorsBody, + }, + ErrorCodes: []errcode.ErrorCode{ + ErrorCodeUnsupported, + }, + }, + }, + }, + }, + }, + // TODO(stevvooe): We may want to add a PUT request here to // kickoff an upload of a blob, integrated with the blob upload // API. @@ -928,7 +991,7 @@ var routeDescriptors = []RouteDescriptor{ { Name: RouteNameBlobUpload, Path: "/v2/{name:" + RepositoryNameRegexp.String() + "}/blobs/uploads/", - Entity: "Intiate Blob Upload", + Entity: "Initiate Blob Upload", Description: "Initiate a blob upload. This endpoint can be used to create resumable uploads or monolithic uploads.", Methods: []MethodDescriptor{ {