diff options
Diffstat (limited to 'doc/book')
-rw-r--r-- | doc/book/build/_index.md | 54 | ||||
-rw-r--r-- | doc/book/build/golang.md | 69 | ||||
-rw-r--r-- | doc/book/build/javascript.md | 55 | ||||
-rw-r--r-- | doc/book/build/others.md (renamed from doc/book/connect/code.md) | 51 | ||||
-rw-r--r-- | doc/book/build/python.md | 95 | ||||
-rw-r--r-- | doc/book/build/rust.md | 47 | ||||
-rw-r--r-- | doc/book/connect/_index.md | 3 | ||||
-rw-r--r-- | doc/book/design/_index.md | 2 | ||||
-rw-r--r-- | doc/book/development/_index.md | 2 | ||||
-rw-r--r-- | doc/book/quick-start/_index.md | 115 | ||||
-rw-r--r-- | doc/book/reference-manual/_index.md | 2 | ||||
-rw-r--r-- | doc/book/reference-manual/admin-api.md | 597 | ||||
-rw-r--r-- | doc/book/working-documents/_index.md | 2 |
13 files changed, 415 insertions, 679 deletions
diff --git a/doc/book/build/_index.md b/doc/book/build/_index.md new file mode 100644 index 00000000..9bb17086 --- /dev/null +++ b/doc/book/build/_index.md @@ -0,0 +1,54 @@ ++++ +title = "Build your own app" +weight = 4 +sort_by = "weight" +template = "documentation.html" ++++ + +Garage has many API that you can rely on to build complex applications. +In this section, we reference the existing SDKs and give some code examples. + + +## ⚠️ DISCLAIMER + +**K2V AND ADMIN 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. + + +## About the APIs + +Code can interact with Garage through 3 different APIs: S3, K2V, and Admin. +Each of them has a specific scope. + +### S3 + +De-facto standard, introduced by Amazon, designed to store blobs of data. + +### K2V + +A simple database API similar to RiakKV or DynamoDB. +Think a key value store with some additional operations. +Its design is inspired by Distributed Hash Tables (DHT). + +More information: + - [In the reference manual](@/documentation/reference-manual/k2v.md) + + +### Administration + +Garage operations can also be automated through a REST API. +We are currently building this SDK for [Python](@/documentation/build/python.md#admin-api), [Javascript](@/documentation/build/javascript.md#administration) and [Golang](@/documentation/build/golang.md#administration). + +More information: + - [In the reference manual](@/documentation/reference-manual/admin-api.md) + - [Full specifiction](https://garagehq.deuxfleurs.fr/api/garage-admin-v0.html) diff --git a/doc/book/build/golang.md b/doc/book/build/golang.md new file mode 100644 index 00000000..a508260e --- /dev/null +++ b/doc/book/build/golang.md @@ -0,0 +1,69 @@ ++++ +title = "Golang" +weight = 30 ++++ + +## S3 + +*Coming soon* + +Some refs: + - Minio minio-go-sdk + - [Reference](https://docs.min.io/docs/golang-client-api-reference.html) + + - Amazon aws-sdk-go-v2 + - [Installation](https://aws.github.io/aws-sdk-go-v2/docs/getting-started/) + - [Reference](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3) + - [Example](https://aws.github.io/aws-sdk-go-v2/docs/code-examples/s3/putobject/) + +## K2V + +*Coming soon* + +## Administration + +Install the SDK with: + +```bash +go get git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang +``` + +A short example: + +```go +package main + +import ( + "context" + "fmt" + "os" + garage "git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang" +) + +func main() { + // Set Host and other parameters + configuration := garage.NewConfiguration() + configuration.Host = "127.0.0.1:3903" + + + // We can now generate a client + client := garage.NewAPIClient(configuration) + + // Authentication is handled through the context pattern + ctx := context.WithValue(context.Background(), garage.ContextAccessToken, "s3cr3t") + + // Send a request + resp, r, err := client.NodesApi.GetNodes(ctx).Execute() + if err != nil { + fmt.Fprintf(os.Stderr, "Error when calling `NodesApi.GetNodes``: %v\n", err) + fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r) + } + + // Process the response + fmt.Fprintf(os.Stdout, "Target hostname: %v\n", resp.KnownNodes[resp.Node].Hostname) +} +``` + +See also: + - [generated doc](https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang) + - [examples](https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-generator/src/branch/main/example/golang) diff --git a/doc/book/build/javascript.md b/doc/book/build/javascript.md new file mode 100644 index 00000000..ff009ffe --- /dev/null +++ b/doc/book/build/javascript.md @@ -0,0 +1,55 @@ ++++ +title = "Javascript" +weight = 10 ++++ + +## S3 + +*Coming soon*. + +Some refs: + - Minio SDK + - [Reference](https://docs.min.io/docs/javascript-client-api-reference.html) + + - Amazon aws-sdk-js + - [Installation](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/getting-started.html) + - [Reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html) + - [Example](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/s3-example-creating-buckets.html) + +## K2V + +*Coming soon* + +## Administration + +Install the SDK with: + +```bash +npm install --save git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git +``` + +A short example: + +```javascript +const garage = require('garage_administration_api_v0garage_v0_8_0'); + +const api = new garage.ApiClient("http://127.0.0.1:3903/v0"); +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: + - [sdk repository](https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js) + - [examples](https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-generator/src/branch/main/example/javascript) diff --git a/doc/book/connect/code.md b/doc/book/build/others.md index 4b2c4cb0..341e82d5 100644 --- a/doc/book/connect/code.md +++ b/doc/book/build/others.md @@ -1,8 +1,10 @@ +++ -title = "Your code (PHP, JS, Go...)" -weight = 30 +title = "Others" +weight = 99 +++ +## S3 + If you are developping a new application, you may want to use Garage to store your user's media. The S3 API that Garage uses is a standard REST API, so as long as you can make HTTP requests, @@ -13,44 +15,14 @@ Instead, there are some libraries already avalaible. Some of them are maintained by Amazon, some by Minio, others by the community. -## PHP +### PHP - Amazon aws-sdk-php - [Installation](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/getting-started_installation.html) - [Reference](https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html) - [Example](https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-examples-creating-buckets.html) -## Javascript - - - Minio SDK - - [Reference](https://docs.min.io/docs/javascript-client-api-reference.html) - - - Amazon aws-sdk-js - - [Installation](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/getting-started.html) - - [Reference](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html) - - [Example](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/s3-example-creating-buckets.html) - -## Golang - - - Minio minio-go-sdk - - [Reference](https://docs.min.io/docs/golang-client-api-reference.html) - - - Amazon aws-sdk-go-v2 - - [Installation](https://aws.github.io/aws-sdk-go-v2/docs/getting-started/) - - [Reference](https://pkg.go.dev/github.com/aws/aws-sdk-go-v2/service/s3) - - [Example](https://aws.github.io/aws-sdk-go-v2/docs/code-examples/s3/putobject/) - -## Python - - - Minio SDK - - [Reference](https://docs.min.io/docs/python-client-api-reference.html) - - - Amazon boto3 - - [Installation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) - - [Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html) - - [Example](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-uploading-files.html) - -## Java +### Java - Minio SDK - [Reference](https://docs.min.io/docs/java-client-api-reference.html) @@ -60,23 +32,18 @@ Some of them are maintained by Amazon, some by Minio, others by the community. - [Reference](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/S3Client.html) - [Example](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/examples-s3-objects.html) -## Rust - - - Amazon aws-rust-sdk - - [Github](https://github.com/awslabs/aws-sdk-rust) - -## .NET +### .NET - Minio SDK - [Reference](https://docs.min.io/docs/dotnet-client-api-reference.html) - Amazon aws-dotnet-sdk -## C++ +### C++ - Amazon aws-cpp-sdk -## Haskell +### Haskell - Minio SDK - [Reference](https://docs.min.io/docs/haskell-client-api-reference.html) diff --git a/doc/book/build/python.md b/doc/book/build/python.md new file mode 100644 index 00000000..19912e85 --- /dev/null +++ b/doc/book/build/python.md @@ -0,0 +1,95 @@ ++++ +title = "Python" +weight = 20 ++++ + +## S3 + +*Coming soon* + +Some refs: + - Minio SDK + - [Reference](https://docs.min.io/docs/python-client-api-reference.html) + + - Amazon boto3 + - [Installation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) + - [Reference](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/s3.html) + - [Example](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-uploading-files.html) + +## K2V + +*Coming soon* + +## Admin API + +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: + +```bash +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`: + +```python +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/v0", + 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({ + status.node: NodeClusterInfo( + zone = "dc1", + capacity = 1, + 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: + - [sdk repo](https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-python) + - [examples](https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-generator/src/branch/main/example/python) + diff --git a/doc/book/build/rust.md b/doc/book/build/rust.md new file mode 100644 index 00000000..7101ba6e --- /dev/null +++ b/doc/book/build/rust.md @@ -0,0 +1,47 @@ ++++ +title = "Rust" +weight = 40 ++++ + +## S3 + +*Coming soon* + +Some refs: + - Amazon aws-rust-sdk + - [Github](https://github.com/awslabs/aws-sdk-rust) + +## K2V + +*Coming soon* + +Some refs: https://git.deuxfleurs.fr/Deuxfleurs/garage/src/branch/main/src/k2v-client + +```bash +# all these values can be provided on the cli instead +export AWS_ACCESS_KEY_ID=GK123456 +export AWS_SECRET_ACCESS_KEY=0123..789 +export AWS_REGION=garage +export K2V_ENDPOINT=http://172.30.2.1:3903 +export K2V_BUCKET=my-bucket + +cargo run --features=cli -- read-range my-partition-key --all + +cargo run --features=cli -- insert my-partition-key my-sort-key --text "my string1" +cargo run --features=cli -- insert my-partition-key my-sort-key --text "my string2" +cargo run --features=cli -- insert my-partition-key my-sort-key2 --text "my string" + +cargo run --features=cli -- read-range my-partition-key --all + +causality=$(cargo run --features=cli -- read my-partition-key my-sort-key2 -b | head -n1) +cargo run --features=cli -- delete my-partition-key my-sort-key2 -c $causality + +causality=$(cargo run --features=cli -- read my-partition-key my-sort-key -b | head -n1) +cargo run --features=cli -- insert my-partition-key my-sort-key --text "my string3" -c $causality + +cargo run --features=cli -- read-range my-partition-key --all +``` + +## Admin API + +*Coming soon* diff --git a/doc/book/connect/_index.md b/doc/book/connect/_index.md index 07c4e31f..ca44ac17 100644 --- a/doc/book/connect/_index.md +++ b/doc/book/connect/_index.md @@ -1,5 +1,5 @@ +++ -title = "Integrations" +title = "Existing integrations" weight = 3 sort_by = "weight" template = "documentation.html" @@ -14,7 +14,6 @@ In particular, you will find here instructions to connect it with: - [Applications](@/documentation/connect/apps/index.md) - [Website hosting](@/documentation/connect/websites.md) - [Software repositories](@/documentation/connect/repositories.md) - - [Your own code](@/documentation/connect/code.md) - [FUSE](@/documentation/connect/fs.md) ### Generic instructions diff --git a/doc/book/design/_index.md b/doc/book/design/_index.md index f3a08aaf..a3a6ac11 100644 --- a/doc/book/design/_index.md +++ b/doc/book/design/_index.md @@ -1,6 +1,6 @@ +++ title = "Design" -weight = 5 +weight = 6 sort_by = "weight" template = "documentation.html" +++ diff --git a/doc/book/development/_index.md b/doc/book/development/_index.md index 662ec358..8e730bf6 100644 --- a/doc/book/development/_index.md +++ b/doc/book/development/_index.md @@ -1,6 +1,6 @@ +++ title = "Development" -weight = 6 +weight = 7 sort_by = "weight" template = "documentation.html" +++ diff --git a/doc/book/quick-start/_index.md b/doc/book/quick-start/_index.md index 21331dcb..03c542f9 100644 --- a/doc/book/quick-start/_index.md +++ b/doc/book/quick-start/_index.md @@ -42,15 +42,16 @@ you can [build Garage from source](@/documentation/cookbook/from-source.md). ## Configuring and starting Garage -### Writing a first configuration file +### Generating a first configuration file This first configuration file should allow you to get started easily with the simplest possible Garage deployment. -**Save it as `/etc/garage.toml`.** -You can also store it somewhere else, but you will have to specify `-c path/to/garage.toml` -at each invocation of the `garage` binary (for example: `garage -c ./garage.toml server`, `garage -c ./garage.toml status`). -```toml +We will create it with the following command line +to generate unique and private secrets for security reasons: + +```bash +cat > garage.toml <<EOF metadata_dir = "/tmp/meta" data_dir = "/tmp/data" @@ -58,7 +59,7 @@ replication_mode = "none" rpc_bind_addr = "[::]:3901" rpc_public_addr = "127.0.0.1:3901" -rpc_secret = "1799bccfd7411eddcf9ebd316bc1f5287ad12a68094e1c6ac6abde7e6feae1ec" +rpc_secret = "$(openssl rand -hex 32)" bootstrap_peers = [] @@ -71,12 +72,26 @@ root_domain = ".s3.garage.localhost" bind_addr = "[::]:3902" root_domain = ".web.garage.localhost" index = "index.html" + +[k2v_api] +api_bind_addr = "[::]:3904" + +[admin] +api_bind_addr = "0.0.0.0:3903" +admin_token = "$(openssl rand -base64 32)" +EOF ``` -The `rpc_secret` value provided above is just an example. It will work, but in -order to secure your cluster you will need to use another one. You can generate -such a value with `openssl rand -hex 32`. +Now that your configuration file has been created, you can put +it in the right place. By default, garage looks at **`/etc/garage.toml`.** +You can also store it somewhere else, but you will have to specify `-c path/to/garage.toml` +at each invocation of the `garage` binary (for example: `garage -c ./garage.toml server`, `garage -c ./garage.toml status`). + +As you can see, the `rpc_secret` is a 32 bytes hexadecimal string. +You can regenerate it with `openssl rand -hex 32`. +If you target a cluster deployment with multiple nodes, make sure that +you use the same value for all nodes. As you can see in the `metadata_dir` and `data_dir` parameters, we are saving Garage's data in `/tmp` which gets erased when your system reboots. This means that data stored on this @@ -219,6 +234,7 @@ Now that we have a bucket and a key, we need to give permissions to the key on t garage bucket allow \ --read \ --write \ + --owner \ nextcloud-bucket \ --key nextcloud-app-key ``` @@ -232,54 +248,73 @@ garage bucket info nextcloud-bucket ## Uploading and downlading from Garage -We recommend the use of MinIO Client to interact with Garage files (`mc`). -Instructions to install it and use it are provided on the -[MinIO website](https://docs.min.io/docs/minio-client-quickstart-guide.html). -Before reading the following, you need a working `mc` command on your path. +To download and upload files on garage, we can use a third-party tool named `awscli`. + -Note that on certain Linux distributions such as Arch Linux, the Minio client binary -is called `mcli` instead of `mc` (to avoid name clashes with the Midnight Commander). +### Install and configure `awscli` -### Configure `mc` +If you have python on your system, you can install it with: -You need your access key and secret key created above. -We will assume you are invoking `mc` on the same machine as the Garage server, -your S3 API endpoint is therefore `http://127.0.0.1:3900`. -For this whole configuration, you must set an alias name: we chose `my-garage`, that you will used for all commands. +```bash +python -m pip install --user awscli +``` -Adapt the following command accordingly and run it: +Now that `awscli` is installed, you must configure it to talk to your Garage instance, +with your key. There are multiple ways to do that, the simplest one is to create a file +named `~/.awsrc` with this content: ```bash -mc alias set \ - my-garage \ - http://127.0.0.1:3900 \ - <access key> \ - <secret key> \ - --api S3v4 +export AWS_ACCESS_KEY_ID=xxxx # put your Key ID here +export AWS_SECRET_ACCESS_KEY=xxxx # put your Secret key here +export AWS_DEFAULT_REGION='garage' +export AWS_ENDPOINT='http://localhost:3900' + +function aws { command aws --endpoint-url $AWS_ENDPOINT $@ ; } +aws --version ``` -### Use `mc` +Now, each time you want to use `awscli` on this target, run: + +```bash +source ~/.awsrc +``` -You can not list buckets from `mc` currently. +*You can create multiple files with different names if you +have multiple Garage clusters or different keys. +Switching from one cluster to another is as simple as +sourcing the right file.* -But the following commands and many more should work: +### Example usage of `awscli` ```bash -mc cp image.png my-garage/nextcloud-bucket -mc cp my-garage/nextcloud-bucket/image.png . -mc ls my-garage/nextcloud-bucket -mc mirror localdir/ my-garage/another-bucket +# list buckets +aws s3 ls + +# list objects of a bucket +aws s3 ls s3://my_files + +# copy from your filesystem to garage +aws s3 cp /proc/cpuinfo s3://my_files/cpuinfo.txt + +# copy from garage to your filesystem +aws s3 cp s3/my_files/cpuinfo.txt /tmp/cpuinfo.txt ``` +Note that you can use `awscli` for more advanced operations like +creating a bucket, pre-signing a request or managing your website. +[Read the full documentation to know more](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3/index.html). + +Some features are however not implemented like ACL or policy. +Check [our s3 compatibility list](@/documentation/reference-manual/s3-compatibility.md). ### Other tools for interacting with Garage The following tools can also be used to send and recieve files from/to Garage: -- the [AWS CLI](https://aws.amazon.com/cli/) -- [`rclone`](https://rclone.org/) -- [Cyberduck](https://cyberduck.io/) -- [`s3cmd`](https://s3tools.org/s3cmd) +- [minio-client](@/documentation/connect/cli.md#minio-client) +- [s3cmd](@/documentation/connect/cli.md#s3cmd) +- [rclone](@/documentation/connect/cli.md#rclone) +- [Cyberduck](@/documentation/connect/cli.md#cyberduck) +- [WinSCP](@/documentation/connect/cli.md#winscp) -Refer to the ["Integrations" section](@/documentation/connect/_index.md) to learn how to -configure application and command line utilities to integrate with Garage. +An exhaustive list is maintained in the ["Integrations" > "Browsing tools" section](@/documentation/connect/_index.md). diff --git a/doc/book/reference-manual/_index.md b/doc/book/reference-manual/_index.md index 62716df8..ab1de5e6 100644 --- a/doc/book/reference-manual/_index.md +++ b/doc/book/reference-manual/_index.md @@ -1,6 +1,6 @@ +++ title = "Reference Manual" -weight = 4 +weight = 5 sort_by = "weight" template = "documentation.html" +++ diff --git a/doc/book/reference-manual/admin-api.md b/doc/book/reference-manual/admin-api.md index 3a4a7aab..0b7e2e16 100644 --- a/doc/book/reference-manual/admin-api.md +++ b/doc/book/reference-manual/admin-api.md @@ -47,598 +47,13 @@ Returns internal Garage metrics in Prometheus format. ### Cluster operations -#### GetClusterStatus `GET /v0/status` +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). -Returns the cluster's current status in JSON, including: +Requesting the API from the command line can be as simple as running: -- ID of the node being queried and its version of the Garage daemon -- Live nodes -- Currently configured cluster layout -- Staged changes to the cluster layout - -Example response body: - -```json -{ - "node": "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f", - "garage_version": "git:v0.8.0", - "knownNodes": { - "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f": { - "addr": "10.0.0.11:3901", - "is_up": true, - "last_seen_secs_ago": 9, - "hostname": "node1" - }, - "4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff": { - "addr": "10.0.0.12:3901", - "is_up": true, - "last_seen_secs_ago": 1, - "hostname": "node2" - }, - "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27": { - "addr": "10.0.0.21:3901", - "is_up": true, - "last_seen_secs_ago": 7, - "hostname": "node3" - }, - "e2ee7984ee65b260682086ec70026165903c86e601a4a5a501c1900afe28d84b": { - "addr": "10.0.0.22:3901", - "is_up": true, - "last_seen_secs_ago": 1, - "hostname": "node4" - } - }, - "layout": { - "version": 12, - "roles": { - "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f": { - "zone": "dc1", - "capacity": 4, - "tags": [ - "node1" - ] - }, - "4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff": { - "zone": "dc1", - "capacity": 6, - "tags": [ - "node2" - ] - }, - "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27": { - "zone": "dc2", - "capacity": 10, - "tags": [ - "node3" - ] - } - }, - "stagedRoleChanges": { - "e2ee7984ee65b260682086ec70026165903c86e601a4a5a501c1900afe28d84b": { - "zone": "dc2", - "capacity": 5, - "tags": [ - "node4" - ] - } - } - } -} -``` - -#### ConnectClusterNodes `POST /v0/connect` - -Instructs this Garage node to connect to other Garage nodes at specified addresses. - -Example request body: - -```json -[ - "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f@10.0.0.11:3901", - "4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff@10.0.0.12:3901" -] -``` - -The format of the string for a node to connect to is: `<node ID>@<ip address>:<port>`, same as in the `garage node connect` CLI call. - -Example response: - -```json -[ - { - "success": true, - "error": null - }, - { - "success": false, - "error": "Handshake error" - } -] -``` - -#### GetClusterLayout `GET /v0/layout` - -Returns the cluster's current layout in JSON, including: - -- Currently configured cluster layout -- Staged changes to the cluster layout - -(the info returned by this endpoint is a subset of the info returned by GetClusterStatus) - -Example response body: - -```json -{ - "version": 12, - "roles": { - "ec79480e0ce52ae26fd00c9da684e4fa56658d9c64cdcecb094e936de0bfe71f": { - "zone": "dc1", - "capacity": 4, - "tags": [ - "node1" - ] - }, - "4a6ae5a1d0d33bf895f5bb4f0a418b7dc94c47c0dd2eb108d1158f3c8f60b0ff": { - "zone": "dc1", - "capacity": 6, - "tags": [ - "node2" - ] - }, - "23ffd0cdd375ebff573b20cc5cef38996b51c1a7d6dbcf2c6e619876e507cf27": { - "zone": "dc2", - "capacity": 10, - "tags": [ - "node3" - ] - } - }, - "stagedRoleChanges": { - "e2ee7984ee65b260682086ec70026165903c86e601a4a5a501c1900afe28d84b": { - "zone": "dc2", - "capacity": 5, - "tags": [ - "node4" - ] - } - } -} -``` - -#### UpdateClusterLayout `POST /v0/layout` - -Send modifications to the cluster layout. These modifications will -be included in the staged role changes, visible in subsequent calls -of `GetClusterLayout`. Once the set of staged changes is satisfactory, -the user may call `ApplyClusterLayout` to apply the changed changes, -or `Revert ClusterLayout` to clear all of the staged changes in -the layout. - -Request body format: - -```json -{ - <node_id>: { - "capacity": <new_capacity>, - "zone": <new_zone>, - "tags": [ - <new_tag>, - ... - ] - }, - <node_id_to_remove>: null, - ... -} -``` - -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. - - -#### ApplyClusterLayout `POST /v0/layout/apply` - -Applies to the cluster the layout changes currently registered as -staged layout changes. - -Request body format: - -```json -{ - "version": 13 -} -``` - -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` - -Clears all of the staged layout changes. - -Request body format: - -```json -{ - "version": 13 -} -``` - -Reverting the staged changes is done by incrementing the version number -and clearing the contents of the staged change list. -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. - - -### Access key operations - -#### ListKeys `GET /v0/key` - -Returns all API access keys in the cluster. - -Example response: - -```json -[ - { - "id": "GK31c2f218a2e44f485b94239e", - "name": "test" - }, - { - "id": "GKe10061ac9c2921f09e4c5540", - "name": "test2" - } -] -``` - -#### 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>` - -Returns information about the requested API access key. - -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). - -Example response: - -```json -{ - "name": "test", - "accessKeyId": "GK31c2f218a2e44f485b94239e", - "secretAccessKey": "b892c0665f0ada8a4755dae98baa3b133590e11dae3bcc1f9d769d67f16c3835", - "permissions": { - "createBucket": false - }, - "buckets": [ - { - "id": "70dc3bed7fe83a75e46b66e7ddef7d56e65f3c02f9f80b6749fb97eccb5e1033", - "globalAliases": [ - "test2" - ], - "localAliases": [], - "permissions": { - "read": true, - "write": true, - "owner": false - } - }, - { - "id": "d7452a935e663fc1914f3a5515163a6d3724010ce8dfd9e4743ca8be5974f995", - "globalAliases": [ - "test3" - ], - "localAliases": [], - "permissions": { - "read": true, - "write": true, - "owner": false - } - }, - { - "id": "e6a14cd6a27f48684579ec6b381c078ab11697e6bc8513b72b2f5307e25fff9b", - "globalAliases": [], - "localAliases": [ - "test" - ], - "permissions": { - "read": true, - "write": true, - "owner": true - } - }, - { - "id": "96470e0df00ec28807138daf01915cfda2bee8eccc91dea9558c0b4855b5bf95", - "globalAliases": [ - "alex" - ], - "localAliases": [], - "permissions": { - "read": true, - "write": true, - "owner": true - } - } - ] -} -``` - -#### DeleteKey `DELETE /v0/key?id=<acces key id>` - -Deletes an API access key. - -#### UpdateKey `POST /v0/key?id=<acces key id>` - -Updates information about the specified API access key. - -Request body format: - -```json -{ - "name": "NameOfMyKey", - "allow": { - "createBucket": true, - }, - "deny": {} -} -``` - -All fields (`name`, `allow` and `deny`) are optionnal. -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`. - - -### Bucket operations - -#### ListBuckets `GET /v0/bucket` - -Returns all storage buckets in the cluster. - -Example response: - -```json -[ - { - "id": "70dc3bed7fe83a75e46b66e7ddef7d56e65f3c02f9f80b6749fb97eccb5e1033", - "globalAliases": [ - "test2" - ], - "localAliases": [] - }, - { - "id": "96470e0df00ec28807138daf01915cfda2bee8eccc91dea9558c0b4855b5bf95", - "globalAliases": [ - "alex" - ], - "localAliases": [] - }, - { - "id": "d7452a935e663fc1914f3a5515163a6d3724010ce8dfd9e4743ca8be5974f995", - "globalAliases": [ - "test3" - ], - "localAliases": [] - }, - { - "id": "e6a14cd6a27f48684579ec6b381c078ab11697e6bc8513b72b2f5307e25fff9b", - "globalAliases": [], - "localAliases": [ - { - "accessKeyId": "GK31c2f218a2e44f485b94239e", - "alias": "test" - } - ] - } -] -``` - -#### GetBucketInfo `GET /v0/bucket?id=<bucket id>` -#### GetBucketInfo `GET /v0/bucket?globalAlias=<alias>` - -Returns information about the requested storage bucket. - -If `id` is set, the bucket is looked up using its exact identifier. -If `globalAlias` is set, the bucket is looked up using its global alias. -(both are fast) - -Example response: - -```json -{ - "id": "afa8f0a22b40b1247ccd0affb869b0af5cff980924a20e4b5e0720a44deb8d39", - "globalAliases": [], - "websiteAccess": false, - "websiteConfig": null, - "keys": [ - { - "accessKeyId": "GK31c2f218a2e44f485b94239e", - "name": "Imported key", - "permissions": { - "read": true, - "write": true, - "owner": true - }, - "bucketLocalAliases": [ - "debug" - ] - } - ], - "objects": 14827, - "bytes": 13189855625, - "unfinshedUploads": 0, - "quotas": { - "maxSize": null, - "maxObjects": null - } -} -``` - -#### CreateBucket `POST /v0/bucket` - -Creates a new storage bucket. - -Request body format: - -```json -{ - "globalAlias": "NameOfMyBucket" -} -``` - -OR - -```json -{ - "localAlias": { - "accessKeyId": "GK31c2f218a2e44f485b94239e", - "alias": "NameOfMyBucket", - "allow": { - "read": true, - "write": true, - "owner": false - } - } -} -``` - -OR - -```json -{} -``` - -Creates a new bucket, either with a global alias, a local one, -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>` - -Updates configuration of the given bucket. - -Request body format: - -```json -{ - "websiteAccess": { - "enabled": true, - "indexDocument": "index.html", - "errorDocument": "404.html" - }, - "quotas": { - "maxSize": 19029801, - "maxObjects": null, - } -} -``` - -All fields (`websiteAccess` and `quotas`) are optionnal. -If they are present, the corresponding modifications are applied to the bucket, otherwise nothing is changed. - -In `websiteAccess`: if `enabled` is `true`, `indexDocument` must be specified. -The field `errorDocument` is optional, if no error document is set a generic -error message is displayed when errors happen. Conversely, if `enabled` is -`false`, neither `indexDocument` nor `errorDocument` must be specified. - -In `quotas`: new values of `maxSize` and `maxObjects` must both be specified, or set to `null` -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. - -### Operations on permissions for keys on buckets - -#### BucketAllowKey `POST /v0/bucket/allow` - -Allows a key to do read/write/owner operations on a bucket. - -Request body format: - -```json -{ - "bucketId": "e6a14cd6a27f48684579ec6b381c078ab11697e6bc8513b72b2f5307e25fff9b", - "accessKeyId": "GK31c2f218a2e44f485b94239e", - "permissions": { - "read": true, - "write": true, - "owner": true - }, -} -``` - -Flags in `permissions` which have the value `true` will be activated. -Other flags will remain unchanged. - -#### BucketDenyKey `POST /v0/bucket/deny` - -Denies a key from doing read/write/owner operations on a bucket. - -Request body format: - -```json -{ - "bucketId": "e6a14cd6a27f48684579ec6b381c078ab11697e6bc8513b72b2f5307e25fff9b", - "accessKeyId": "GK31c2f218a2e44f485b94239e", - "permissions": { - "read": false, - "write": false, - "owner": true - }, -} +```bash +curl -H 'Authorization: Bearer s3cr3t' http://localhost:3903/v0/status | jq ``` -Flags in `permissions` which have the value `true` will be deactivated. -Other flags will remain unchanged. - - -### Operations on bucket aliases - -#### GlobalAliasBucket `PUT /v0/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>` - -Removes a global alias for a bucket. - -#### LocalAliasBucket `PUT /v0/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>` - -Removes a local alias for a bucket in the namespace of a specific access key. - +For more advanced use cases, we recommend using a SDK. +[Go to the "Build your own app" section to know how to use our SDKs](@/documentation/build/_index.md) diff --git a/doc/book/working-documents/_index.md b/doc/book/working-documents/_index.md index 9871d206..8fc170b7 100644 --- a/doc/book/working-documents/_index.md +++ b/doc/book/working-documents/_index.md @@ -1,6 +1,6 @@ +++ title = "Working Documents" -weight = 7 +weight = 8 sort_by = "weight" template = "documentation.html" +++ |