aboutsummaryrefslogtreecommitdiff
path: root/doc/drafts
diff options
context:
space:
mode:
Diffstat (limited to 'doc/drafts')
-rw-r--r--doc/drafts/admin-api.md306
1 files changed, 186 insertions, 120 deletions
diff --git a/doc/drafts/admin-api.md b/doc/drafts/admin-api.md
index fb71dc83..411f6418 100644
--- a/doc/drafts/admin-api.md
+++ b/doc/drafts/admin-api.md
@@ -52,11 +52,11 @@ Returns an HTTP status 200 if the node is ready to answer user's requests,
and an HTTP status 503 (Service Unavailable) if there are some partitions
for which a quorum of nodes is not available.
A simple textual message is also returned in a body with content-type `text/plain`.
-See `/v0/health` for an API that also returns JSON output.
+See `/v1/health` for an API that also returns JSON output.
### Cluster operations
-#### GetClusterStatus `GET /v0/status`
+#### GetClusterStatus `GET /v1/status`
Returns the cluster's current status in JSON, including:
@@ -70,86 +70,112 @@ Example response body:
```json
{
"node": "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f",
- "garage_version": "git:v0.8.0",
- "knownNodes": {
- "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f": {
+ "garageVersion": "git:v0.9.0-dev",
+ "garageFeatures": [
+ "k2v",
+ "sled",
+ "lmdb",
+ "sqlite",
+ "metrics",
+ "bundled-libs"
+ ],
+ "rustVersion": "1.68.0",
+ "dbEngine": "LMDB (using Heed crate)",
+ "knownNodes": [
+ {
+ "id": "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f",
"addr": "10.0.0.11:3901",
- "is_up": true,
- "last_seen_secs_ago": 9,
+ "isUp": true,
+ "lastSeenSecsAgo": 9,
"hostname": "node1"
},
- "4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff": {
+ {
+ "id": "4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff",
"addr": "10.0.0.12:3901",
- "is_up": true,
- "last_seen_secs_ago": 1,
+ "isUp": true,
+ "lastSeenSecsAgo": 1,
"hostname": "node2"
},
- "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27": {
+ {
+ "id": "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27",
"addr": "10.0.0.21:3901",
- "is_up": true,
- "last_seen_secs_ago": 7,
+ "isUp": true,
+ "lastSeenSecsAgo": 7,
"hostname": "node3"
},
- "e2ee7984ee65b260682086ec70026165903c86e601a4a5a501c1900afe28d84b": {
+ {
+ "id": "e2ee7984ee65b260682086ec70026165903c86e601a4a5a501c1900afe28d84b",
"addr": "10.0.0.22:3901",
- "is_up": true,
- "last_seen_secs_ago": 1,
+ "isUp": true,
+ "lastSeenSecsAgo": 1,
"hostname": "node4"
}
- },
+ ],
"layout": {
"version": 12,
- "roles": {
- "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f": {
+ "roles": [
+ {
+ "id": "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f",
"zone": "dc1",
- "capacity": 4,
+ "capacity": 10737418240,
"tags": [
"node1"
]
},
- "4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff": {
+ {
+ "id": "4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff",
"zone": "dc1",
- "capacity": 6,
+ "capacity": 10737418240,
"tags": [
"node2"
]
},
- "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27": {
+ {
+ "id": "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27",
"zone": "dc2",
- "capacity": 10,
+ "capacity": 10737418240,
"tags": [
"node3"
]
}
- },
- "stagedRoleChanges": {
- "e2ee7984ee65b260682086ec70026165903c86e601a4a5a501c1900afe28d84b": {
+ ],
+ "stagedRoleChanges": [
+ {
+ "id": "e2ee7984ee65b260682086ec70026165903c86e601a4a5a501c1900afe28d84b",
+ "remove": false,
"zone": "dc2",
- "capacity": 5,
+ "capacity": 10737418240,
"tags": [
"node4"
]
}
- }
+ {
+ "id": "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27",
+ "remove": true,
+ "zone": null,
+ "capacity": null,
+ "tags": null,
+ }
+ ]
}
}
```
-#### GetClusterHealth `GET /v0/health`
+#### GetClusterHealth `GET /v1/health`
Returns the cluster's current health in JSON format, with the following variables:
-- `status`: one of `Healthy`, `Degraded` or `Unavailable`:
- - Healthy: Garage node is connected to all storage nodes
- - Degraded: Garage node is not connected to all storage nodes, but a quorum of write nodes is available for all partitions
- - Unavailable: a quorum of write nodes is not available for some partitions
-- `known_nodes`: the number of nodes this Garage node has had a TCP connection to since the daemon started
-- `connected_nodes`: the nubmer of nodes this Garage node currently has an open connection to
-- `storage_nodes`: the number of storage nodes currently registered in the cluster layout
-- `storage_nodes_ok`: the number of storage nodes to which a connection is currently open
+- `status`: one of `healthy`, `degraded` or `unavailable`:
+ - healthy: Garage node is connected to all storage nodes
+ - degraded: Garage node is not connected to all storage nodes, but a quorum of write nodes is available for all partitions
+ - unavailable: a quorum of write nodes is not available for some partitions
+- `knownNodes`: the number of nodes this Garage node has had a TCP connection to since the daemon started
+- `connectedNodes`: the nubmer of nodes this Garage node currently has an open connection to
+- `storageNodes`: the number of storage nodes currently registered in the cluster layout
+- `storageNodesOk`: the number of storage nodes to which a connection is currently open
- `partitions`: the total number of partitions of the data (currently always 256)
-- `partitions_quorum`: the number of partitions for which a quorum of write nodes is available
-- `partitions_all_ok`: the number of partitions for which we are connected to all storage nodes responsible of storing it
+- `partitionsQuorum`: the number of partitions for which a quorum of write nodes is available
+- `partitionsAllOk`: the number of partitions for which we are connected to all storage nodes responsible of storing it
Contrarily to `GET /health`, this endpoint always returns a 200 OK HTTP response code.
@@ -157,18 +183,18 @@ Example response body:
```json
{
- "status": "Degraded",
- "known_nodes": 3,
- "connected_nodes": 2,
- "storage_nodes": 3,
- "storage_nodes_ok": 2,
- "partitions": 256,
- "partitions_quorum": 256,
- "partitions_all_ok": 0
+ "status": "degraded",
+ "knownNodes": 3,
+ "connectedNodes": 3,
+ "storageNodes": 4,
+ "storageNodesOk": 3,
+ "partitions": 256,
+ "partitionsQuorum": 256,
+ "partitionsAllOk": 64
}
```
-#### ConnectClusterNodes `POST /v0/connect`
+#### ConnectClusterNodes `POST /v1/connect`
Instructs this Garage node to connect to other Garage nodes at specified addresses.
@@ -198,7 +224,7 @@ Example response:
]
```
-#### GetClusterLayout `GET /v0/layout`
+#### GetClusterLayout `GET /v1/layout`
Returns the cluster's current layout in JSON, including:
@@ -212,42 +238,54 @@ Example response body:
```json
{
"version": 12,
- "roles": {
- "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f": {
+ "roles": [
+ {
+ "id": "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f",
"zone": "dc1",
- "capacity": 4,
+ "capacity": 10737418240,
"tags": [
"node1"
]
},
- "4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff": {
+ {
+ "id": "4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff",
"zone": "dc1",
- "capacity": 6,
+ "capacity": 10737418240,
"tags": [
"node2"
]
},
- "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27": {
+ {
+ "id": "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27",
"zone": "dc2",
- "capacity": 10,
+ "capacity": 10737418240,
"tags": [
"node3"
]
}
- },
- "stagedRoleChanges": {
- "e2ee7984ee65b260682086ec70026165903c86e601a4a5a501c1900afe28d84b": {
+ ],
+ "stagedRoleChanges": [
+ {
+ "id": "e2ee7984ee65b260682086ec70026165903c86e601a4a5a501c1900afe28d84b",
+ "remove": false,
"zone": "dc2",
- "capacity": 5,
+ "capacity": 10737418240,
"tags": [
"node4"
]
}
- }
+ {
+ "id": "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27",
+ "remove": true,
+ "zone": null,
+ "capacity": null,
+ "tags": null,
+ }
+ ]
}
```
-#### UpdateClusterLayout `POST /v0/layout`
+#### UpdateClusterLayout `POST /v1/layout`
Send modifications to the cluster layout. These modifications will
be included in the staged role changes, visible in subsequent calls
@@ -259,8 +297,9 @@ the layout.
Request body format:
```json
-{
- <node_id>: {
+[
+ {
+ "id": <node_id>,
"capacity": <new_capacity>,
"zone": <new_zone>,
"tags": [
@@ -268,17 +307,22 @@ Request body format:
...
]
},
- <node_id_to_remove>: null,
- ...
-}
+ {
+ "id": <node_id_to_remove>,
+ "remove": true
+ }
+]
```
Contrary to the CLI that may update only a subset of the fields
`capacity`, `zone` and `tags`, when calling this API all of these
values must be specified.
+This returns the new cluster layout with the proposed staged changes,
+as returned by GetClusterLayout.
+
-#### ApplyClusterLayout `POST /v0/layout/apply`
+#### ApplyClusterLayout `POST /v1/layout/apply`
Applies to the cluster the layout changes currently registered as
staged layout changes.
@@ -295,7 +339,10 @@ Similarly to the CLI, the body must include the version of the new layout
that will be created, which MUST be 1 + the value of the currently
existing layout in the cluster.
-#### RevertClusterLayout `POST /v0/layout/revert`
+This returns the message describing all the calculations done to compute the new
+layout, as well as the description of the layout as returned by GetClusterLayout.
+
+#### RevertClusterLayout `POST /v1/layout/revert`
Clears all of the staged layout changes.
@@ -313,10 +360,13 @@ Similarly to the CLI, the body must include the incremented
version number, which MUST be 1 + the value of the currently
existing layout in the cluster.
+This returns the new cluster layout with all changes reverted,
+as returned by GetClusterLayout.
+
### Access key operations
-#### ListKeys `GET /v0/key`
+#### ListKeys `GET /v1/key`
Returns all API access keys in the cluster.
@@ -335,34 +385,8 @@ Example response:
]
```
-#### CreateKey `POST /v0/key`
-
-Creates a new API access key.
-
-Request body format:
-
-```json
-{
- "name": "NameOfMyKey"
-}
-```
-
-#### ImportKey `POST /v0/key/import`
-
-Imports an existing API key.
-
-Request body format:
-
-```json
-{
- "accessKeyId": "GK31c2f218a2e44f485b94239e",
- "secretAccessKey": "b892c0665f0ada8a4755dae98baa3b133590e11dae3bcc1f9d769d67f16c3835",
- "name": "NameOfMyKey"
-}
-```
-
-#### GetKeyInfo `GET /v0/key?id=<acces key id>`
-#### GetKeyInfo `GET /v0/key?search=<pattern>`
+#### GetKeyInfo `GET /v1/key?id=<acces key id>`
+#### GetKeyInfo `GET /v1/key?search=<pattern>`
Returns information about the requested API access key.
@@ -370,6 +394,9 @@ If `id` is set, the key is looked up using its exact identifier (faster).
If `search` is set, the key is looked up using its name or prefix
of identifier (slower, all keys are enumerated to do this).
+Optionnally, the query parameter `showSecretKey=true` can be set to reveal the
+associated secret access key.
+
Example response:
```json
@@ -433,11 +460,40 @@ Example response:
}
```
-#### DeleteKey `DELETE /v0/key?id=<acces key id>`
+#### CreateKey `POST /v1/key`
-Deletes an API access key.
+Creates a new API access key.
-#### UpdateKey `POST /v0/key?id=<acces key id>`
+Request body format:
+
+```json
+{
+ "name": "NameOfMyKey"
+}
+```
+
+This returns the key info, including the created secret key,
+in the same format as the result of GetKeyInfo.
+
+#### ImportKey `POST /v1/key/import`
+
+Imports an existing API key.
+This will check that the imported key is in the valid format, i.e.
+is a key that could have been generated by Garage.
+
+Request body format:
+
+```json
+{
+ "accessKeyId": "GK31c2f218a2e44f485b94239e",
+ "secretAccessKey": "b892c0665f0ada8a4755dae98baa3b133590e11dae3bcc1f9d769d67f16c3835",
+ "name": "NameOfMyKey"
+}
+```
+
+This returns the key info in the same format as the result of GetKeyInfo.
+
+#### UpdateKey `POST /v1/key?id=<acces key id>`
Updates information about the specified API access key.
@@ -457,10 +513,16 @@ All fields (`name`, `allow` and `deny`) are optional.
If they are present, the corresponding modifications are applied to the key, otherwise nothing is changed.
The possible flags in `allow` and `deny` are: `createBucket`.
+This returns the key info in the same format as the result of GetKeyInfo.
+
+#### DeleteKey `DELETE /v1/key?id=<acces key id>`
+
+Deletes an API access key.
+
### Bucket operations
-#### ListBuckets `GET /v0/bucket`
+#### ListBuckets `GET /v1/bucket`
Returns all storage buckets in the cluster.
@@ -502,8 +564,8 @@ Example response:
]
```
-#### GetBucketInfo `GET /v0/bucket?id=<bucket id>`
-#### GetBucketInfo `GET /v0/bucket?globalAlias=<alias>`
+#### GetBucketInfo `GET /v1/bucket?id=<bucket id>`
+#### GetBucketInfo `GET /v1/bucket?globalAlias=<alias>`
Returns information about the requested storage bucket.
@@ -535,7 +597,10 @@ Example response:
],
"objects": 14827,
"bytes": 13189855625,
- "unfinshedUploads": 0,
+ "unfinishedUploads": 1,
+ "unfinishedMultipartUploads": 1,
+ "unfinishedMultipartUploadParts": 11,
+ "unfinishedMultipartUploadBytes": 41943040,
"quotas": {
"maxSize": null,
"maxObjects": null
@@ -543,7 +608,7 @@ Example response:
}
```
-#### CreateBucket `POST /v0/bucket`
+#### CreateBucket `POST /v1/bucket`
Creates a new storage bucket.
@@ -583,13 +648,7 @@ or no alias at all.
Technically, you can also specify both `globalAlias` and `localAlias` and that would create
two aliases, but I don't see why you would want to do that.
-#### DeleteBucket `DELETE /v0/bucket?id=<bucket id>`
-
-Deletes a storage bucket. A bucket cannot be deleted if it is not empty.
-
-Warning: this will delete all aliases associated with the bucket!
-
-#### UpdateBucket `PUT /v0/bucket?id=<bucket id>`
+#### UpdateBucket `PUT /v1/bucket?id=<bucket id>`
Updates configuration of the given bucket.
@@ -621,9 +680,16 @@ In `quotas`: new values of `maxSize` and `maxObjects` must both be specified, or
to remove the quotas. An absent value will be considered the same as a `null`. It is not possible
to change only one of the two quotas.
+#### DeleteBucket `DELETE /v1/bucket?id=<bucket id>`
+
+Deletes a storage bucket. A bucket cannot be deleted if it is not empty.
+
+Warning: this will delete all aliases associated with the bucket!
+
+
### Operations on permissions for keys on buckets
-#### BucketAllowKey `POST /v0/bucket/allow`
+#### BucketAllowKey `POST /v1/bucket/allow`
Allows a key to do read/write/owner operations on a bucket.
@@ -644,7 +710,7 @@ Request body format:
Flags in `permissions` which have the value `true` will be activated.
Other flags will remain unchanged.
-#### BucketDenyKey `POST /v0/bucket/deny`
+#### BucketDenyKey `POST /v1/bucket/deny`
Denies a key from doing read/write/owner operations on a bucket.
@@ -668,19 +734,19 @@ Other flags will remain unchanged.
### Operations on bucket aliases
-#### GlobalAliasBucket `PUT /v0/bucket/alias/global?id=<bucket id>&alias=<global alias>`
+#### GlobalAliasBucket `PUT /v1/bucket/alias/global?id=<bucket id>&alias=<global alias>`
Empty body. Creates a global alias for a bucket.
-#### GlobalUnaliasBucket `DELETE /v0/bucket/alias/global?id=<bucket id>&alias=<global alias>`
+#### GlobalUnaliasBucket `DELETE /v1/bucket/alias/global?id=<bucket id>&alias=<global alias>`
Removes a global alias for a bucket.
-#### LocalAliasBucket `PUT /v0/bucket/alias/local?id=<bucket id>&accessKeyId=<access key ID>&alias=<local alias>`
+#### LocalAliasBucket `PUT /v1/bucket/alias/local?id=<bucket id>&accessKeyId=<access key ID>&alias=<local alias>`
Empty body. Creates a local alias for a bucket in the namespace of a specific access key.
-#### LocalUnaliasBucket `DELETE /v0/bucket/alias/local?id=<bucket id>&accessKeyId<access key ID>&alias=<local alias>`
+#### LocalUnaliasBucket `DELETE /v1/bucket/alias/local?id=<bucket id>&accessKeyId<access key ID>&alias=<local alias>`
Removes a local alias for a bucket in the namespace of a specific access key.