9.1 KiB
Garage Admin SDK
Operate your Garage cluster programatically
⚠️ DISCLAIMER
THESE SDK ARE TECHNICAL PREVIEWS. The following limitations apply:
- The API is not complete, some actions are possible only through the
garage
binary - The underlying admin API is not yet stable nor complete, it can breaks at any time
- The generator configuration is currently tweaked, the library might break at any time due to a generator change
- Because the API and the library are not stable, none of them are published in a package manager (npm, pypi, etc.)
- This code has not been extensively tested, some things might not work (please report!)
To have the best experience possible, please consider:
- Make sure that the version of the library you are using is pinned (
go.sum
,package-lock.json
,requirements.txt
). - Before upgrading your Garage cluster, make sure that you can find a version of this SDK that works with your targeted version and that you are able to update your own code to work with this new version of the library.
- Join our Matrix channel at
#garage:deuxfleurs.fr
, say that you are interested by this SDK, and report any friction. - If stability is critical, mirror this repository on your own infrastructure, regenerate the SDKs and upgrade them at your own pace.
For SDK users
The following languages are supported:
Python
You need at least Python 3.6, pip, and setuptools. Because the python package is in a subfolder, the command is a bit more complicated than usual:
pip3 install --user 'git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-python'
Now, let imagine you have a fresh Garage instance running on localhost, with the admin API configured on port 3903 with the bearer s3cr3t
:
import garage_admin_sdk
from garage_admin_sdk.apis import *
from garage_admin_sdk.models import *
configuration = garage_admin_sdk.Configuration(
host = "http://localhost:3903/v1",
access_token = "s3cr3t"
)
# Init APIs
api = garage_admin_sdk.ApiClient(configuration)
nodes, layout, keys, buckets = NodesApi(api), LayoutApi(api), KeyApi(api), BucketApi(api)
# Display some info on the node
status = nodes.get_nodes()
print(f"running garage {status.garage_version}, node_id {status.node}")
# Change layout of this node
current = layout.get_layout()
layout.add_layout([
NodeRoleChange(
id = status.node,
zone = "dc1",
capacity = 1000000000,
tags = [ "dev" ],
)
])
layout.apply_layout(LayoutVersion(
version = current.version + 1
))
# Create key, allow it to create buckets
kinfo = keys.add_key(AddKeyRequest(name="openapi"))
allow_create = UpdateKeyRequestAllow(create_bucket=True)
keys.update_key(kinfo.access_key_id, UpdateKeyRequest(allow=allow_create))
# Create a bucket, allow key, set quotas
binfo = buckets.create_bucket(CreateBucketRequest(global_alias="documentation"))
binfo = buckets.allow_bucket_key(AllowBucketKeyRequest(
bucket_id=binfo.id,
access_key_id=kinfo.access_key_id,
permissions=AllowBucketKeyRequestPermissions(read=True, write=True, owner=True),
))
binfo = buckets.update_bucket(binfo.id, UpdateBucketRequest(
quotas=UpdateBucketRequestQuotas(max_size=19029801,max_objects=1500)))
# Display key
print(f"""
cluster ready
key id is {kinfo.access_key_id}
secret key is {kinfo.secret_access_key}
bucket {binfo.global_aliases[0]} contains {binfo.objects}/{binfo.quotas.max_objects} objects
""")
This example is named short.py
in the example folder. Other python examples are also available.
See also:
Javascript
Install the SDK with:
npm install --save git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git
A short example:
const garage = require('garage_administration_api_v1garage_v0_9_0');
const api = new garage.ApiClient("http://127.0.0.1:3903/v1");
api.authentications['bearerAuth'].accessToken = "s3cr3t";
const [node, layout, key, bucket] = [
new garage.NodesApi(api),
new garage.LayoutApi(api),
new garage.KeyApi(api),
new garage.BucketApi(api),
];
node.getNodes().then((data) => {
console.log(`nodes: ${Object.values(data.knownNodes).map(n => n.hostname)}`)
}, (error) => {
console.error(error);
});
See also:
Golang
Install the SDK with:
go get git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang
An example without error checking:
package main
import (
"context"
"fmt"
"os"
"strings"
garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang"
)
func main() {
// Initialization
configuration := garage.NewConfiguration()
configuration.Host = "127.0.0.1:3903"
client := garage.NewAPIClient(configuration)
ctx := context.WithValue(context.Background(), garage.ContextAccessToken, "s3cr3t")
// Nodes
fmt.Println("--- nodes ---")
nodes, _, _ := client.NodesApi.GetNodes(ctx).Execute()
fmt.Fprintf(os.Stdout, "First hostname: %v\n", nodes.KnownNodes[0].Hostname)
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
health, _, _ := client.NodesApi.GetHealth(ctx).Execute()
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))
}
See also:
For SDK developpers
PR are accepted for other languages as soon as good examples are provided. Especially, we want them to be meaningful, manually written, and covering a large range of the API. Thanks in advance :-)
Clone this repo
git clone ...
git submodule update --init
(Re)generate libraries
# Check the OpenAPI spec file
gradle validate
# (re)build the python client
gradle buildPythonClient
# (re)build the Go client
gradle buildGoClient
# (re)build the javascrit cient
gradle buildJavascriptClient
Support a new language
Read the doc: https://openapi-generator.tech/docs/installation
We use the Gradle plugins: https://openapi-generator.tech/docs/plugins
Many generators exist: https://openapi-generator.tech/docs/generators