Dynamic read-only mode for individual repositories
Context
The container registry has a read-only mode which disallows write requests to all repositories in the registry. This feature is a requisite to run offline garbage collection and migrate object storage without downtime. Toggling this read-only mode requires the registry to be restarted.
Instead of locking the whole registry with a global read-only mode, it would be useful to lock individual repositories/namespaces. A repository may be set to read-only mode if undergoing maintenance or to archive and protect it from any changes (similar to how a branch can be protected). Ideally, this should be done online, without requiring a restart of the registry.
Overview
All write API operations are scoped by repository, which means that we can parse the target repository from the request URI and allow or disallow requests depending on whether the repository is in read-only mode.
The status of the read-only mode for each repository should be persisted centrally, from where all registry instances can read. Additionally, an API route should be exposed to allow privileged users to toggle the read-only mode for a specific repository and read its status.
Middleware
On the registry API, a new middleware should be developed and attached to the request processing pipeline with the following duties for each inbound write (POST
, PUT
, PATCH
or DELETE
) request:
- Parse repository namespace from request URI;
- Check if the repository is said to be in read-only mode;
- If in read-only mode return a
405 Method Not Allowed
response, otherwise fulfill the request.
This middleware should be injected after the auth middleware so that we don't have to do this validation for unauthorized requests.
This is how the interaction between client and registry should look like:
sequenceDiagram
autonumber
participant C as Client
participant R as Registry
participant D as Database
C->>R: POST/PUT/PATCH/DELETE /v2/<name>/...
R->>D: Is repository <name> in read-only mode?
alt Repository in read-only mode
D->>R: Yes
R->>C: 405 Method Not Allowed
else Repository in read/write mode
D->>R: No
R->>R: Fulfill request
R->>C: Response
end
Admin API
The registry should expose a new API endpoint to manage the list of read-only repositories at run time, which would be accessible to privileged users only.
PATCH /api/v1/repositories/<name>
This operation allows administrators to toggle the read-only mode attribute for a given repository.
Request
Attribute | Type | Required | Description |
---|---|---|---|
readonly |
Boolean | Yes | Wether read-only mode should be turned on or off. |
Example
{
"readonly": true
}
Response
204 No Content
Request successfully processed.
404 Not Found
Repository not found.
GET /api/v1/repositories
This route allows administrators to obtain a list of repositories.
Request
Query Parameters
Attribute | Type | Description |
---|---|---|
readonly |
Boolean | Filter repositories by their read-only mode status. |
Response
200 OK
The response body is a list of objects, one per repository, with the following attributes:
Attribute | Type | Description |
---|---|---|
name |
String | Repository name. |
readonly |
Boolean | If the repository is in read-only mode. |
readonly_on_at |
Datetime | Timestamp at which the read-only mode was last turned on. |
readonly_off_at |
Datetime | Timestamp at which the read-only mode was last turned off. |
Example
[
{
"name": "gitlab-org/foo",
"readonly": true,
"readonly_on_at": "2020-08-12T13:49:36",
},
{
"name": "gitlab-org/bar",
"readonly": false,
"readonly_on_at": "2020-08-12T13:49:36",
"readonly_off_at": "2020-08-12T13:50:12"
}
]
GET /api/v1/repositories/<name>
This route allows administrators to obtain the status of a specific repository.
Response
200 OK
The response body is an object with the following attributes:
Attribute | Type | Description |
---|---|---|
name |
String | Repository name. |
readonly |
Boolean | If the repository is in read-only mode. |
readonly_on_at |
Datetime | Timestamp at which the read-only mode was last turned on. |
readonly_off_at |
Datetime | Timestamp at which the read-only mode was last turned off. |
Example
[
{
"name": "gitlab-org/bar",
"readonly": false,
"readonly_on_at": "2020-08-12T13:49:36",
"readonly_off_at": "2020-08-12T13:50:12"
}
]
404 Not Found
Repository not found.
Database
The implementation of this feature can only be done once the registry metadata database is complete (&2313 (closed)). The readonly
, readonly_on_at
and readonly_off_at
attributes should be persisted in three new columns on the repositories
table.