api-v1, generator #2
16 changed files with 358 additions and 58 deletions
97
README.md
97
README.md
|
@ -41,7 +41,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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,13 +55,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
|
||||||
))
|
))
|
||||||
|
@ -108,9 +109,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] = [
|
||||||
|
@ -139,7 +140,7 @@ Install the SDK with:
|
||||||
go get git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang
|
go get git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang
|
||||||
```
|
```
|
||||||
|
|
||||||
A short example:
|
An example without error checking:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
package main
|
package main
|
||||||
|
@ -148,30 +149,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))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
14
build.gradle
14
build.gradle
|
@ -3,40 +3,40 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
task validate(type: org.openapitools.generator.gradle.plugin.tasks.ValidateTask){
|
task validate(type: org.openapitools.generator.gradle.plugin.tasks.ValidateTask){
|
||||||
inputSpec = "./garage/doc/api/garage-admin-v0.yml"
|
inputSpec = "./garage/doc/api/garage-admin-v1.yml"
|
||||||
recommend = true
|
recommend = true
|
||||||
}
|
}
|
||||||
|
|
||||||
task buildPythonClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
|
task buildPythonClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
|
||||||
generatorName = "python"
|
generatorName = "python"
|
||||||
inputSpec = "./garage/doc/api/garage-admin-v0.yml"
|
inputSpec = "./garage/doc/api/garage-admin-v1.yml"
|
||||||
outputDir = "$rootDir/garage-admin-sdk-python"
|
outputDir = "$rootDir/garage-admin-sdk-python"
|
||||||
gitHost = "git.deuxfleurs.fr"
|
gitHost = "git.deuxfleurs.fr"
|
||||||
gitUserId = "garage-sdk"
|
gitUserId = "garage-sdk"
|
||||||
gitRepoId = "garage-admin-sdk-python"
|
gitRepoId = "garage-admin-sdk-python"
|
||||||
configOptions = [
|
configOptions = [
|
||||||
packageName: "garage_admin_sdk",
|
packageName: "garage_admin_sdk",
|
||||||
packageVersion: "0.8.0",
|
packageVersion: "0.9.0",
|
||||||
projectName: "garage-admin-sdk-python"
|
projectName: "garage-admin-sdk-python"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
task buildGoClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
|
task buildGoClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
|
||||||
generatorName = "go"
|
generatorName = "go"
|
||||||
inputSpec = "./garage/doc/api/garage-admin-v0.yml"
|
inputSpec = "./garage/doc/api/garage-admin-v1.yml"
|
||||||
outputDir = "$rootDir/garage-admin-sdk-golang"
|
outputDir = "$rootDir/garage-admin-sdk-golang"
|
||||||
gitHost = "git.deuxfleurs.fr"
|
gitHost = "git.deuxfleurs.fr"
|
||||||
gitUserId = "garage-sdk"
|
gitUserId = "garage-sdk"
|
||||||
gitRepoId = "garage-admin-sdk-golang"
|
gitRepoId = "garage-admin-sdk-golang"
|
||||||
configOptions = [
|
configOptions = [
|
||||||
packageName: "garage",
|
packageName: "garage",
|
||||||
packageVersion: "0.8.0"
|
packageVersion: "0.9.0"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
task buildJavascriptClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
|
task buildJavascriptClient(type: org.openapitools.generator.gradle.plugin.tasks.GenerateTask) {
|
||||||
generatorName = "javascript"
|
generatorName = "javascript"
|
||||||
inputSpec = "./garage/doc/api/garage-admin-v0.yml"
|
inputSpec = "./garage/doc/api/garage-admin-v1.yml"
|
||||||
outputDir = "$rootDir/garage-admin-sdk-js"
|
outputDir = "$rootDir/garage-admin-sdk-js"
|
||||||
gitHost = "git.deuxfleurs.fr"
|
gitHost = "git.deuxfleurs.fr"
|
||||||
gitUserId = "garage-sdk"
|
gitUserId = "garage-sdk"
|
||||||
|
@ -46,7 +46,7 @@ task buildJavascriptClient(type: org.openapitools.generator.gradle.plugin.tasks.
|
||||||
moduleName: "garage",
|
moduleName: "garage",
|
||||||
npmName: "garage-admin-sdk-js",
|
npmName: "garage-admin-sdk-js",
|
||||||
npmRepository: "@dxflrs/garage-admin-sdk-js",
|
npmRepository: "@dxflrs/garage-admin-sdk-js",
|
||||||
packageVersion: "0.8.0",
|
packageVersion: "0.9.0",
|
||||||
usePromises: "true",
|
usePromises: "true",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ module garage-admin-example
|
||||||
go 1.18
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20221113145120-d012cff7c554 // indirect
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231128142223-9dd59cf12c08 // indirect
|
||||||
github.com/golang/protobuf v1.4.2 // indirect
|
github.com/golang/protobuf v1.4.2 // indirect
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
|
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
|
||||||
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 // indirect
|
golang.org/x/oauth2 v0.0.0-20210323180902-22b0adad7558 // indirect
|
||||||
|
|
|
@ -33,6 +33,18 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20221113145120-d012cff7c554 h1:GAQabea9CjkmQIDm4MxbG064enYVL69swewbjRfl5G8=
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20221113145120-d012cff7c554 h1:GAQabea9CjkmQIDm4MxbG064enYVL69swewbjRfl5G8=
|
||||||
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20221113145120-d012cff7c554/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20221113145120-d012cff7c554/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231122201735-f442d10b102d h1:GxlTiFj3WwYjULWp/MvW2iETmDf7TpOtEP2Qst2TkwU=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231122201735-f442d10b102d/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231123075451-d89dcefca5d0 h1:lhvMeTcFi72W1+nBg5LVueuFuNaP+2lIn+1Vg4yZvek=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231123075451-d89dcefca5d0/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231123090411-96f080c89ec4 h1:c7xX/UITgwb+7+m4uOB7BXg/pA+BB7EHhsXNMr8UMNY=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231123090411-96f080c89ec4/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231123092113-ffd9578e975e h1:C/D3P1+mWBTHiO3MeiNWB2S1AJ3A/m7OYGX4iS8nbtA=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231123092113-ffd9578e975e/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231128133246-d1fd35809073 h1:2i4BlF34l5ZuCe9rDQbSnvigGxHMtc99qxP55oUuPt4=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231128133246-d1fd35809073/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231128142223-9dd59cf12c08 h1:pPjSXww/2ebfJ4iHt2NI8/cs/eBV+VC9YLQIW0N3E54=
|
||||||
|
git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-golang v0.0.0-20231128142223-9dd59cf12c08/go.mod h1:TlSL6QVxozmdRaSgP6Akspi0HCJv4HAkkq3Dldru4GM=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
|
|
|
@ -4,6 +4,7 @@ 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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -20,12 +21,156 @@ func main() {
|
||||||
ctx := context.WithValue(context.Background(), garage.ContextAccessToken, "s3cr3t")
|
ctx := context.WithValue(context.Background(), garage.ContextAccessToken, "s3cr3t")
|
||||||
|
|
||||||
// Send a request
|
// Send a request
|
||||||
|
fmt.Println("--- nodes ---")
|
||||||
resp, r, err := client.NodesApi.GetNodes(ctx).Execute()
|
resp, r, err := client.NodesApi.GetNodes(ctx).Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Error when calling `NodesApi.GetNodes``: %v\n", err)
|
fmt.Fprintf(os.Stderr, "Error when calling `NodesApi.GetNodes`\n")
|
||||||
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process the response
|
// Process the response
|
||||||
fmt.Fprintf(os.Stdout, "Target hostname: %v\n", resp.KnownNodes[resp.Node].Hostname)
|
fmt.Fprintf(os.Stdout, "First hostname: %v\n", resp.KnownNodes[0].Hostname)
|
||||||
|
|
||||||
|
// Layout
|
||||||
|
capa := int64(1000000000)
|
||||||
|
change := []garage.NodeRoleChange{
|
||||||
|
garage.NodeRoleChange{NodeRoleUpdate: &garage.NodeRoleUpdate {
|
||||||
|
Id: *resp.KnownNodes[0].Id,
|
||||||
|
Zone: "dc1",
|
||||||
|
Capacity: *garage.NewNullableInt64(&capa),
|
||||||
|
Tags: []string{ "fast", "amd64" },
|
||||||
|
}},
|
||||||
|
}
|
||||||
|
staged, r, err := client.LayoutApi.AddLayout(ctx).NodeRoleChange(change).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `LayoutApi.AddLayout`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
msg, r, err := client.LayoutApi.ApplyLayout(ctx).LayoutVersion(*garage.NewLayoutVersion(staged.Version + 1)).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `LayoutApi.ApplyLayout`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf(strings.Join(msg.Message, "\n"))
|
||||||
|
|
||||||
|
// Check health
|
||||||
|
health, r, err := client.NodesApi.GetHealth(ctx).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `NodesApi.GetHealth`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Status: %s\n", health.Status)
|
||||||
|
fmt.Printf("All nodes: %v/%v healthy\n", health.ConnectedNodes, health.KnownNodes)
|
||||||
|
fmt.Printf("Storage nodes: %v/%v healthy\n", health.StorageNodesOk, health.StorageNodes)
|
||||||
|
fmt.Printf("Partitions: %v/%v healthy\n", health.PartitionsAllOk, health.Partitions)
|
||||||
|
|
||||||
|
|
||||||
|
// Key
|
||||||
|
fmt.Println("\n--- key ---")
|
||||||
|
// -- create
|
||||||
|
key := "openapi-key"
|
||||||
|
keyInfo, r, err := client.KeyApi.AddKey(ctx).AddKeyRequest(garage.AddKeyRequest{Name: *garage.NewNullableString(&key) }).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `KeyApi.AddKey`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("AWS_ACCESS_KEY_ID=%s\nAWS_SECRET_ACCESS_KEY=%s\n", *keyInfo.AccessKeyId, *keyInfo.SecretAccessKey.Get())
|
||||||
|
|
||||||
|
// -- delete
|
||||||
|
defer func() {
|
||||||
|
r, err := client.KeyApi.DeleteKey(ctx).Id(*keyInfo.AccessKeyId).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `KeyApi.DeleteKey`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// -- update
|
||||||
|
id := *keyInfo.AccessKeyId
|
||||||
|
canCreateBucket := true
|
||||||
|
updateKeyRequest := *garage.NewUpdateKeyRequest()
|
||||||
|
updateKeyRequest.SetName("openapi-key-updated")
|
||||||
|
updateKeyRequest.SetAllow(garage.UpdateKeyRequestAllow { CreateBucket: &canCreateBucket })
|
||||||
|
update, r, err := client.KeyApi.UpdateKey(ctx).Id(id).UpdateKeyRequest(updateKeyRequest).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `KeyApi.UpdateKey`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Updated %v with key name %v\n", *update.AccessKeyId, *update.Name)
|
||||||
|
|
||||||
|
// -- list
|
||||||
|
keyList, r, err := client.KeyApi.ListKeys(ctx).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `KeyApi.ListKeys`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Keys count: %v\n", len(keyList))
|
||||||
|
|
||||||
|
// Bucket
|
||||||
|
fmt.Println("\n--- bucket ---")
|
||||||
|
// -- create
|
||||||
|
global_name := "global-ns-openapi-bucket"
|
||||||
|
local_name := "local-ns-openapi-bucket"
|
||||||
|
bucketInfo, r, err := client.BucketApi.CreateBucket(ctx).CreateBucketRequest(garage.CreateBucketRequest{
|
||||||
|
GlobalAlias: &global_name,
|
||||||
|
LocalAlias: &garage.CreateBucketRequestLocalAlias {
|
||||||
|
AccessKeyId: keyInfo.AccessKeyId,
|
||||||
|
Alias: &local_name,
|
||||||
|
},
|
||||||
|
}).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `BucketApi.CreateBucket`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Bucket id: %s\n", *bucketInfo.Id)
|
||||||
|
|
||||||
|
// -- delete
|
||||||
|
defer func() {
|
||||||
|
r, err := client.BucketApi.DeleteBucket(ctx).Id(*bucketInfo.Id).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `BucketApi.DeleteBucket`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// -- update
|
||||||
|
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, r, err := client.BucketApi.UpdateBucket(ctx).Id(*bucketInfo.Id).UpdateBucketRequest(updateBucketRequest).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `BucketApi.UpdateBucket`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Bucket %v website activation: %v\n", *updatedBucket.Id, *updatedBucket.WebsiteAccess)
|
||||||
|
|
||||||
|
// -- list
|
||||||
|
bucketList, r, err := client.BucketApi.ListBuckets(ctx).Execute()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "Error when calling `BucketApi.ListBuckets`\n")
|
||||||
|
fmt.Fprintf(os.Stderr, "Full HTTP response: %v\n", r)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Bucket count: %v\n", len(bucketList))
|
||||||
}
|
}
|
||||||
|
|
85
example/golang/short.go
Normal file
85
example/golang/short.go
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
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))
|
||||||
|
}
|
15
example/javascript/package-lock.json
generated
15
example/javascript/package-lock.json
generated
|
@ -9,7 +9,7 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"garage_administration_api_v0garage_v0_8_0": "git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git"
|
"garage_administration_api_v1garage_v0_9_0": "git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git#4e3e8ea9986e427f969ab31be116b7ed95ae8362"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@ampproject/remapping": {
|
"node_modules/@ampproject/remapping": {
|
||||||
|
@ -736,9 +736,10 @@
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||||
},
|
},
|
||||||
"node_modules/garage_administration_api_v0garage_v0_8_0": {
|
"node_modules/garage_administration_api_v1garage_v0_9_0": {
|
||||||
"version": "v0.8.0",
|
"name": "garage_administration_api_v0garage_v0_9_0",
|
||||||
"resolved": "git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git#635d3c1517482099289de1e01c21877b4659208e",
|
"version": "v0.9.0",
|
||||||
|
"resolved": "git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git#4e3e8ea9986e427f969ab31be116b7ed95ae8362",
|
||||||
"license": "Unlicense",
|
"license": "Unlicense",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/cli": "^7.0.0",
|
"@babel/cli": "^7.0.0",
|
||||||
|
@ -1813,9 +1814,9 @@
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||||
},
|
},
|
||||||
"garage_administration_api_v0garage_v0_8_0": {
|
"garage_administration_api_v1garage_v0_9_0": {
|
||||||
"version": "git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git#635d3c1517482099289de1e01c21877b4659208e",
|
"version": "git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git#4e3e8ea9986e427f969ab31be116b7ed95ae8362",
|
||||||
"from": "garage_administration_api_v0garage_v0_8_0@git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git",
|
"from": "garage_administration_api_v1garage_v0_9_0@git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git#4e3e8ea9986e427f969ab31be116b7ed95ae8362",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@babel/cli": "^7.0.0",
|
"@babel/cli": "^7.0.0",
|
||||||
"superagent": "^5.3.0"
|
"superagent": "^5.3.0"
|
||||||
|
|
|
@ -9,6 +9,6 @@
|
||||||
"author": "",
|
"author": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"garage_administration_api_v0garage_v0_8_0": "git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git"
|
"garage_administration_api_v1garage_v0_9_0": "git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-js.git#4e3e8ea9986e427f969ab31be116b7ed95ae8362"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
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] = [
|
||||||
|
|
|
@ -3,7 +3,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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -25,13 +25,14 @@ with garage_admin_sdk.ApiClient(configuration) as api_client:
|
||||||
exit(1)
|
exit(1)
|
||||||
print("it seems to be a fresh node, continuing the configuration")
|
print("it seems to be a fresh node, continuing the configuration")
|
||||||
|
|
||||||
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" ],
|
||||||
)
|
)
|
||||||
})
|
])
|
||||||
print("added myself to the layout")
|
print("added myself to the layout")
|
||||||
|
|
||||||
current = layout.get_layout()
|
current = layout.get_layout()
|
||||||
|
@ -55,7 +56,7 @@ with garage_admin_sdk.ApiClient(configuration) as api_client:
|
||||||
|
|
||||||
# --- UPDATE KEY ---
|
# --- UPDATE KEY ---
|
||||||
# not required here, just to demo the API
|
# not required here, just to demo the API
|
||||||
kinfo = keys.search_key("openapi")
|
kinfo = keys.get_key(search="openapi")
|
||||||
|
|
||||||
allow_create = UpdateKeyRequestAllow(create_bucket=True)
|
allow_create = UpdateKeyRequestAllow(create_bucket=True)
|
||||||
kreq = UpdateKeyRequest(allow=allow_create)
|
kreq = UpdateKeyRequest(allow=allow_create)
|
||||||
|
@ -63,7 +64,7 @@ with garage_admin_sdk.ApiClient(configuration) as api_client:
|
||||||
print(f"key {kinfo.access_key_id} can now create buckets")
|
print(f"key {kinfo.access_key_id} can now create buckets")
|
||||||
|
|
||||||
# update key info
|
# update key info
|
||||||
kinfo = keys.search_key("openapi")
|
kinfo = keys.get_key(search="openapi", show_secret_key="true")
|
||||||
print(f"key permissions: {kinfo.permissions}")
|
print(f"key permissions: {kinfo.permissions}")
|
||||||
|
|
||||||
# ---- THE END ---
|
# ---- THE END ---
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-python@f48df53
|
git+https://git.deuxfleurs.fr/garage-sdk/garage-admin-sdk-python@e02326f5dbdf467c380663a7ecb14bcdfdc88149
|
||||||
|
|
|
@ -3,7 +3,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"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -17,13 +17,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
|
||||||
))
|
))
|
||||||
|
|
2
garage
2
garage
|
@ -1 +1 @@
|
||||||
Subproject commit 30f1636a00ffc60d1c9ac1d3781ccee21669e54d
|
Subproject commit 3908619eac7c46c0d1b065adb4b79db798bc8d22
|
|
@ -1 +1 @@
|
||||||
Subproject commit c965fe7f7dc93b9b9a65ec4015c4e7ede0f6121b
|
Subproject commit 8b81fae65e5e277b2b9e1659dd657f967a6122a9
|
|
@ -1 +1 @@
|
||||||
Subproject commit 635d3c1517482099289de1e01c21877b4659208e
|
Subproject commit 271b95144902afdcdc7912c61936d955595bf48e
|
|
@ -1 +1 @@
|
||||||
Subproject commit f48df53ba21b9b544a503801fe0762c70bd1a5ae
|
Subproject commit 90e64feb060692c0f19c283cace242e207f03190
|
Loading…
Reference in a new issue