forked from Deuxfleurs/garage
Merge pull request 'OpenAPI specification of admin APIv1' (#672) from api-v1 into main
Reviewed-on: Deuxfleurs/garage#672
This commit is contained in:
commit
a8b0e01f88
7 changed files with 1471 additions and 24 deletions
24
doc/api/garage-admin-v1.html
Normal file
24
doc/api/garage-admin-v1.html
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Garage Adminstration API v0</title>
|
||||||
|
<!-- needed for adaptive design -->
|
||||||
|
<meta charset="utf-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link href="./css/redoc.css" rel="stylesheet">
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Redoc doesn't change outer page styles
|
||||||
|
-->
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<redoc spec-url='./garage-admin-v1.yml'></redoc>
|
||||||
|
<script src="./redoc.standalone.js"> </script>
|
||||||
|
</body>
|
||||||
|
</html>
|
1363
doc/api/garage-admin-v1.yml
Normal file
1363
doc/api/garage-admin-v1.yml
Normal file
File diff suppressed because it is too large
Load diff
|
@ -37,30 +37,84 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang"
|
garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Set Host and other parameters
|
// Initialization
|
||||||
configuration := garage.NewConfiguration()
|
configuration := garage.NewConfiguration()
|
||||||
configuration.Host = "127.0.0.1:3903"
|
configuration.Host = "127.0.0.1:3903"
|
||||||
|
|
||||||
|
|
||||||
// We can now generate a client
|
|
||||||
client := garage.NewAPIClient(configuration)
|
client := garage.NewAPIClient(configuration)
|
||||||
|
|
||||||
// Authentication is handled through the context pattern
|
|
||||||
ctx := context.WithValue(context.Background(), garage.ContextAccessToken, "s3cr3t")
|
ctx := context.WithValue(context.Background(), garage.ContextAccessToken, "s3cr3t")
|
||||||
|
|
||||||
// Send a request
|
// Nodes
|
||||||
resp, r, err := client.NodesApi.GetNodes(ctx).Execute()
|
fmt.Println("--- nodes ---")
|
||||||
if err != nil {
|
nodes, _, _ := client.NodesApi.GetNodes(ctx).Execute()
|
||||||
fmt.Fprintf(os.Stderr, "Error when calling `NodesApi.GetNodes``: %v\n", err)
|
fmt.Fprintf(os.Stdout, "First hostname: %v\n", nodes.KnownNodes[0].Hostname)
|
||||||
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
capa := int64(1000000000)
|
||||||
|
change := []garage.NodeRoleChange{
|
||||||
|
garage.NodeRoleChange{NodeRoleUpdate: &garage.NodeRoleUpdate {
|
||||||
|
Id: *nodes.KnownNodes[0].Id,
|
||||||
|
Zone: "dc1",
|
||||||
|
Capacity: *garage.NewNullableInt64(&capa),
|
||||||
|
Tags: []string{ "fast", "amd64" },
|
||||||
|
}},
|
||||||
}
|
}
|
||||||
|
staged, _, _ := client.LayoutApi.AddLayout(ctx).NodeRoleChange(change).Execute()
|
||||||
|
msg, _, _ := client.LayoutApi.ApplyLayout(ctx).LayoutVersion(*garage.NewLayoutVersion(staged.Version + 1)).Execute()
|
||||||
|
fmt.Printf(strings.Join(msg.Message, "\n")) // Layout configured
|
||||||
|
|
||||||
// Process the response
|
health, _, _ := client.NodesApi.GetHealth(ctx).Execute()
|
||||||
fmt.Fprintf(os.Stdout, "Target hostname: %v\n", resp.KnownNodes[resp.Node].Hostname)
|
fmt.Printf("Status: %s, nodes: %v/%v, storage: %v/%v, partitions: %v/%v\n", health.Status, health.ConnectedNodes, health.KnownNodes, health.StorageNodesOk, health.StorageNodes, health.PartitionsAllOk, health.Partitions)
|
||||||
|
|
||||||
|
// Key
|
||||||
|
fmt.Println("\n--- key ---")
|
||||||
|
key := "openapi-key"
|
||||||
|
keyInfo, _, _ := client.KeyApi.AddKey(ctx).AddKeyRequest(garage.AddKeyRequest{Name: *garage.NewNullableString(&key) }).Execute()
|
||||||
|
defer client.KeyApi.DeleteKey(ctx).Id(*keyInfo.AccessKeyId).Execute()
|
||||||
|
fmt.Printf("AWS_ACCESS_KEY_ID=%s\nAWS_SECRET_ACCESS_KEY=%s\n", *keyInfo.AccessKeyId, *keyInfo.SecretAccessKey.Get())
|
||||||
|
|
||||||
|
id := *keyInfo.AccessKeyId
|
||||||
|
canCreateBucket := true
|
||||||
|
updateKeyRequest := *garage.NewUpdateKeyRequest()
|
||||||
|
updateKeyRequest.SetName("openapi-key-updated")
|
||||||
|
updateKeyRequest.SetAllow(garage.UpdateKeyRequestAllow { CreateBucket: &canCreateBucket })
|
||||||
|
update, _, _ := client.KeyApi.UpdateKey(ctx).Id(id).UpdateKeyRequest(updateKeyRequest).Execute()
|
||||||
|
fmt.Printf("Updated %v with key name %v\n", *update.AccessKeyId, *update.Name)
|
||||||
|
|
||||||
|
keyList, _, _ := client.KeyApi.ListKeys(ctx).Execute()
|
||||||
|
fmt.Printf("Keys count: %v\n", len(keyList))
|
||||||
|
|
||||||
|
// Bucket
|
||||||
|
fmt.Println("\n--- bucket ---")
|
||||||
|
global_name := "global-ns-openapi-bucket"
|
||||||
|
local_name := "local-ns-openapi-bucket"
|
||||||
|
bucketInfo, _, _ := client.BucketApi.CreateBucket(ctx).CreateBucketRequest(garage.CreateBucketRequest{
|
||||||
|
GlobalAlias: &global_name,
|
||||||
|
LocalAlias: &garage.CreateBucketRequestLocalAlias {
|
||||||
|
AccessKeyId: keyInfo.AccessKeyId,
|
||||||
|
Alias: &local_name,
|
||||||
|
},
|
||||||
|
}).Execute()
|
||||||
|
defer client.BucketApi.DeleteBucket(ctx).Id(*bucketInfo.Id).Execute()
|
||||||
|
fmt.Printf("Bucket id: %s\n", *bucketInfo.Id)
|
||||||
|
|
||||||
|
updateBucketRequest := *garage.NewUpdateBucketRequest()
|
||||||
|
website := garage.NewUpdateBucketRequestWebsiteAccess()
|
||||||
|
website.SetEnabled(true)
|
||||||
|
website.SetIndexDocument("index.html")
|
||||||
|
website.SetErrorDocument("errors/4xx.html")
|
||||||
|
updateBucketRequest.SetWebsiteAccess(*website)
|
||||||
|
quotas := garage.NewUpdateBucketRequestQuotas()
|
||||||
|
quotas.SetMaxSize(1000000000)
|
||||||
|
quotas.SetMaxObjects(999999999)
|
||||||
|
updateBucketRequest.SetQuotas(*quotas)
|
||||||
|
updatedBucket, _, _ := client.BucketApi.UpdateBucket(ctx).Id(*bucketInfo.Id).UpdateBucketRequest(updateBucketRequest).Execute()
|
||||||
|
fmt.Printf("Bucket %v website activation: %v\n", *updatedBucket.Id, *updatedBucket.WebsiteAccess)
|
||||||
|
|
||||||
|
bucketList, _, _ := client.BucketApi.ListBuckets(ctx).Execute()
|
||||||
|
fmt.Printf("Bucket count: %v\n", len(bucketList))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,9 @@ npm install --save git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.
|
||||||
A short example:
|
A short example:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
const garage = require('garage_administration_api_v0garage_v0_8_0');
|
const garage = require('garage_administration_api_v1garage_v0_9_0');
|
||||||
|
|
||||||
const api = new garage.ApiClient("http://127.0.0.1:3903/v0");
|
const api = new garage.ApiClient("http://127.0.0.1:3903/v1");
|
||||||
api.authentications['bearerAuth'].accessToken = "s3cr3t";
|
api.authentications['bearerAuth'].accessToken = "s3cr3t";
|
||||||
|
|
||||||
const [node, layout, key, bucket] = [
|
const [node, layout, key, bucket] = [
|
||||||
|
|
|
@ -80,7 +80,7 @@ from garage_admin_sdk.apis import *
|
||||||
from garage_admin_sdk.models import *
|
from garage_admin_sdk.models import *
|
||||||
|
|
||||||
configuration = garage_admin_sdk.Configuration(
|
configuration = garage_admin_sdk.Configuration(
|
||||||
host = "http://localhost:3903/v0",
|
host = "http://localhost:3903/v1",
|
||||||
access_token = "s3cr3t"
|
access_token = "s3cr3t"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -94,13 +94,14 @@ print(f"running garage {status.garage_version}, node_id {status.node}")
|
||||||
|
|
||||||
# Change layout of this node
|
# Change layout of this node
|
||||||
current = layout.get_layout()
|
current = layout.get_layout()
|
||||||
layout.add_layout({
|
layout.add_layout([
|
||||||
status.node: NodeClusterInfo(
|
NodeRoleChange(
|
||||||
|
id = status.node,
|
||||||
zone = "dc1",
|
zone = "dc1",
|
||||||
capacity = 1,
|
capacity = 1000000000,
|
||||||
tags = [ "dev" ],
|
tags = [ "dev" ],
|
||||||
)
|
)
|
||||||
})
|
])
|
||||||
layout.apply_layout(LayoutVersion(
|
layout.apply_layout(LayoutVersion(
|
||||||
version = current.version + 1
|
version = current.version + 1
|
||||||
))
|
))
|
||||||
|
|
|
@ -13,8 +13,11 @@ We will bump the version numbers prefixed to each API endpoint at each time the
|
||||||
or semantics change, meaning that code that relies on these endpoint will break
|
or semantics change, meaning that code that relies on these endpoint will break
|
||||||
when changes are introduced.
|
when changes are introduced.
|
||||||
|
|
||||||
The Garage administration API was introduced in version 0.7.2, this document
|
Versions:
|
||||||
does not apply to older versions of Garage.
|
- Before Garage 0.7.2 - no admin API
|
||||||
|
- Garage 0.7.2 - admin APIv0
|
||||||
|
- Garage 0.9.0 - admin APIv1, deprecate admin APIv0
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Access control
|
## Access control
|
||||||
|
@ -131,7 +134,9 @@ $ curl -so /dev/null -w "%{http_code}" http://localhost:3903/check?domain=exampl
|
||||||
|
|
||||||
### Cluster operations
|
### Cluster operations
|
||||||
|
|
||||||
These endpoints are defined on a dedicated [Redocly page](https://garagehq.deuxfleurs.fr/api/garage-admin-v0.html). You can also download its [OpenAPI specification](https://garagehq.deuxfleurs.fr/api/garage-admin-v0.yml).
|
These endpoints have a dedicated OpenAPI spec.
|
||||||
|
- APIv1 - [HTML spec](https://garagehq.deuxfleurs.fr/api/garage-admin-v1.html) - [OpenAPI YAML](https://garagehq.deuxfleurs.fr/api/garage-admin-v1.yml)
|
||||||
|
- APIv0 (deprecated) - [HTML spec](https://garagehq.deuxfleurs.fr/api/garage-admin-v0.html) - [OpenAPI YAML](https://garagehq.deuxfleurs.fr/api/garage-admin-v0.yml)
|
||||||
|
|
||||||
Requesting the API from the command line can be as simple as running:
|
Requesting the API from the command line can be as simple as running:
|
||||||
|
|
||||||
|
|
|
@ -182,7 +182,7 @@ impl AdminApiServer {
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let status_str = format!(
|
let status_str = format!(
|
||||||
"{}\nConsult the full health check API endpoint at /v0/health for more details\n",
|
"{}\nConsult the full health check API endpoint at /v1/health for more details\n",
|
||||||
status_str
|
status_str
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue