インストール
標準ライブラリのみで、Go 1.21 以降が必要です。どの呼び出しも最初に context.Context を取り、エラーは戻り値で返し、オプションは関数オプションで、ストリームは io.Reader と io.Writer です。モジュールは github.com/GlacAI/glac-go で、パッケージは glac です。
go get github.com/GlacAI/glac-goクライアント
製品ごとのフィールドを備えた 1 つのクライアント:
client, err := glac.NewClient() // GLAC_API_KEY and GLAC_API_URL; or glac.NewClient(glac.APIKey(key), glac.BaseURL(address))
if err != nil {
log.Fatal(err)
}
app, err := client.Cube.Deploy(ctx, "ghcr.io/acme/api:1.4", glac.Name("api"), glac.Port(8080)) // Cube: waits until it serves
if err != nil {
log.Fatal(err)
}
fmt.Println(app.URL())
sbx, err := client.Sandboxes.Create(ctx, glac.Image("python:3.12")) // Sandbox
if err != nil {
log.Fatal(err)
}
res, err := sbx.Run(ctx, "python3 -c 'print(6*7)'")
if err != nil {
log.Fatal(err)
}
fmt.Print(res.Stdout)
drive, err := client.Drives.Create(ctx, glac.Name("data"), glac.SizeBytes(10<<30)) // Drive
if err != nil {
log.Fatal(err)
}
fmt.Println(drive.ID)自前のクライアントを必要としない唯一の呼び出しは、1 つのコマンドのためのサンドボックスで、デフォルトのクライアント(必要になった時点で環境変数から作られる)を使います。
res, err := glac.Sandboxes.Run(ctx, "echo hello") // one call: make, run, delete
if err != nil {
log.Fatal(err)
}
fmt.Print(res.Stdout)各製品はクライアントのフィールドで(go-github と同じく、そのクライアントで呼び出しを行うサービス)、プラットフォーム自体の呼び出しはクライアントのメソッドです。
| 場所 | 項目 | 呼び出し |
|---|---|---|
client.Cube |
キューブ:それぞれ固有のアドレスでサービスとして動くイメージ(API ではアプリ:/v1/apps、型は App)。client.Workers は別名の同じサービスで、非推奨 |
Deploy, Create, Get, GetOrCreate, List |
client.Sandboxes |
サンドボックス(/v1/sandboxes) |
Run, Create, Get, GetOrCreate, List, ListPage |
client.Sandboxes.Snapshots |
サンドボックスのスナップショット | Get, List |
client.Sandboxes.SSHKeys |
サンドボックスを開く SSH キー | Create, Get, List |
client.Drives |
ドライブ:サンドボックスより長く残るプロジェクトのディスクで、それぞれ一度に 1 つのサンドボックスが読み書き可能でマウントする。そのスナップショットは、いくつでも同時に読み取り専用でマウントできる(/v1/drives、コントロールプレーンの機能。型は Drive と DriveSnapshot) |
Create, Get, List, ListPage, Rename, Delete, Attach, Detach, ForceDetach; Snapshot, Snapshots, GetSnapshot, DeleteSnapshot, Fork, Restore, AttachSnapshot, DetachSnapshot, ForceDetachSnapshot |
client.Volumes |
ドライブの下にあるボリューム(/v1/volumes。型は Volume) |
Create, Get, List, Backup, Backups |
client.Backups |
ボリュームのバックアップ:ある瞬間のボリューム全体のコピーで、オブジェクトストアにあり、ボリュームより長く残る(/v1/backups、コントロールプレーンの機能。型は Backup) |
List, ListOf, Get, Delete, Restore |
client.Domains |
プロジェクトの独自ドメイン(/v1/domains。コントロールプレーンの機能。型は Domain) |
Create, Get, List, Delete |
client.Webhooks, client.Keys |
プロジェクトのイベントの送信先(/v1/webhooks)と API キー(/v1/keys)。コントロールプレーンの機能 |
Create、Get、List、Update(Webhook のみ)、Delete |
client.Destinations |
プロジェクトのアプリのログ、メトリクス、トレースのエクスポート先(/v1/destinations)。コントロールプレーンの機能 |
Create, Get, List, Update, Delete, Test |
client.Secrets, client.Variables |
プロジェクトのシークレットと共有変数 | Put、Update(シークレットのホスト)、List、Delete |
client.Deploys |
プロジェクトのデプロイ:複数のサービスをまとめてデプロイする(/v1/deploys、コントロールプレーンの機能。型は Deploy) |
Create, Get, List |
client 自体 |
プラットフォーム:アカウント、使用量、請求と残高、プロジェクトとそのイベント | GetAccount, UpdateAccount, GetUsage, GetUsageReport, GetBilling, UpdateBilling, GetBalance, UpdateBalance, TopUp, ListCharges, ListLedger, GetProject, ListEvents, Request |
glac.Sandboxes |
デフォルトのクライアントのサンドボックス(Snapshots と SSHKeys を含む) |
client.Sandboxes と同じ呼び出しを、デフォルトのクライアントで行う。環境変数からクライアントを作れない場合は、それぞれその理由を返す |
キーは GLAC_API_KEY から、アドレスは GLAC_API_URL(デフォルトは https://api.glac.ai)から読みます。glac.NewClient(glac.APIKey(…), glac.BaseURL(…), glac.RequestTimeout(d), glac.Retries(n), glac.HTTPClient(…), glac.OnResponse(f)) で、別のアドレス、キー、タイムアウト、再試行回数を指定できます。SDK がラップしていない API は client.Request(ctx, "GET", "/v1/webhooks", nil, nil, &out) で呼びます。
キューブ
キューブ(API ではアプリ)は、固有のアドレスでサービスとして動くイメージ(ここでの型は App)で、インスタンスはリクエストに必要なだけ動き、リクエストがなければ 1 つもありません。デプロイのたびにバージョンが作られ、準備ができた時点でアプリのトラフィックを受け取ります。
client.Cube.Deploy(ctx, image, …) は、glac deploy と同じことをします。Name を指定すると、その名前のアプリにイメージのバージョンが作られ、アプリがなければ作成されます。指定しなければ新しいアプリが作られ、API が名前を付けます。バージョンがトラフィックを受け取るまで待ち、その時点のアプリを返します(app.URL()、app.CurrentVersion())。
app, err = client.Cube.Deploy(ctx, "ghcr.io/acme/api:1.5", glac.Name("api"), glac.MinInstances(1)) // the app is there: MinInstances is changed first, then a version is made
var failed *glac.DeployError
if errors.As(err, &failed) {
log.Fatalf("version %d did not come up: %s", failed.Version.Number, failed.Code()) // the traffic stayed where it was
} else if err != nil {
log.Fatal(err)
}
fmt.Println(app.CurrentVersion())- 既存のアプリでは、すぐに反映されるもの(
Regions、スケール、キー、WithEgress、Metadata、ログの設定、トレースの設定、Public、DependsOn、Aliases、EndpointMode)を、指定がある場合に限り、app.Updateと同じように先に変更します。次に、app.Deployと同じように、バージョンを構成するもの(Image、Port、Env、Secrets、StartLine、VCPUs、Volumes、Drives、KeyDrivesなど)からバージョンを作ります。指定しないものはアプリのものが使われ、EnvとSecretsは指定したものがバージョンのすべてになります。存在しないアプリ(404app_not_found)は、Createと同じように、すべてを指定して作られます。その間に誰かが作ったアプリ(409name_taken)には、既存のアプリとしてデプロイします。 - その他の呼び出し。
client.Cube.Create、Get、GetOrCreate、List。アプリに対しては、app.Deploy(バージョン:*AppVersion)、app.Update、app.Version(ctx, "3")、app.Versions、app.Rollback(ctx, "1")、app.Logs(ctx, glac.Follow())、app.LogUsage、app.DeleteLogs、app.Metrics(ctx, from, to, "minute")(アプリを処理するマシンが計測した値を 1 分ごと、または 1 時間ごとに:メトリクス)、Create、Deploy、app.Updateのglac.TraceSampleRate(0.1)とglac.TrustIncomingTrace(true)、app.Info().Traces(アプリのリクエストの一定割合について作られるプラットフォームのスパンで、インスタンス自身のスパンはその子になる。指定しなければなし。tracesを受け付けるプロジェクトのエクスポート先に送られる:トレース)、app.Info().LogsState(ログを保持する各マシンが、今そこで出力されるものを長期保存しているかどうか:ログ)、app.Instance(ctx, key)(キーのために保持されるインスタンス)、app.CreateKeySecret、app.KeySecrets、app.KeySecret(ctx, id)、app.DeleteKeySecret(アプリのキーの署名に使うシークレット)、glac.SignKey(secret, app.ID, key, expires)(エッジを通るリクエストが運ぶ形の署名付きキー。glac.PathSegmentはそれをパスのセグメントとして書く:署名付きキー)、app.Deleteです。 - **待機。**バージョンをビルドする呼び出しは、
glac.NoWait()を指定しない限り、それを待ちます。立ち上がらなかったバージョンは*glac.DeployErrorになり、そのCode()はバージョン自身のもの(boot_failed、image_not_foundなど)です。アプリのトラフィックは元のままで、アプリはエラーとともに返ります。 - ランタイム設定。
glac.Runtime(glac.ServiceRuntime{…})で、バージョンにランタイム設定を与えます。Docker の名前によるプロセスの制限、Docker がコンテナに設定を許すカーネル設定、メモリ上のファイルシステム、リゾルバー、/dev/shmのサイズで、全体が置き換わります。 - チェックポイント。
glac.Checkpoint(n)(n 秒ごと。1〜600。0 ならデフォルトの 10 秒ごと)は、アプリのキー別インスタンスの稼働中にチェックポイントを取るようにし、glac.NoCheckpoint()はそれを解除します。どちらもアプリ自体の設定で、Cube.Create、Cube.Deploy、app.Updateが受け付け、AppInfo.Checkpoint(*AppCheckpoint。なければnil)が設定を示します。インスタンスのSandboxInfo.Checkpoint(*SandboxCheckpoint:EverySeconds、LastAt、BehindSeconds、BytesPerSecond、StoredBytes、Error。なければnil)が、チェックポイントの状況を示します。 - キーのインスタンスのバージョン。
inst.Upgrade(ctx, "3")(またはapp.UpgradeInstance(ctx, key, version))は、キーのインスタンスをアプリの別のバージョンへその場で移します。""はアプリの現在のバージョンで、それ以外は ID か番号です(準備ができたもので、古いものも可)。ID、ノード、キー、アドレス、トークン、専用のドライブはそのままで、ディスク、マシン、プロセスが新しいバージョンのものになり、切り替えの間、リクエストはエッジで保留されます。進行中の*Upgradeを返します(Statusはpreparing、switching、done、failed。FromVersion、ToVersion、Timings、Error、PutBack。Kind(upgradeまたはrevert)、When、KeepDays、Rollback(リバートに必要なもの。KeepDaysの間保持される)、Reverts、Batch。API でインスタンスのスリープを待つよう求めたアップグレードは、スリープするまでwaitingで、取り消された場合(API のDELETE、またはバッチの停止)はcancelledになります。取り消されたアップグレードは終了しており、その待機は失敗したものと同じく、コードcancelledで例外になります)。すでにそのバージョンならnilを返し、エラーにはなりません。up.Wait(ctx)は終わるまで待ち、新しいバージョンが立ち上がらなかった場合は、インスタンスを元のバージョンのままにして、型がupgrade_failedの*Error(Codeはupgrade_failedかupgrade_not_here)を返します。inst.Upgrades(ctx)、app.InstanceUpgrades(ctx, key)、app.InstanceUpgrade(ctx, key, id)で読み取り、inst.Refresh(ctx)でインスタンスを読み直します(VersionID)。バージョンの後のオプション:glac.WhenAsleep()は、インスタンスがスリープするまで待ち(waiting)、スリープした時点で始めるため、リクエストは 1 つも保留されません。glac.KeepDays(n)(0〜365 日、指定しなければ 7 日)は、完了後にリバートに必要なものを保持する日数で、スナップショットと同じく課金されます。インスタンスとは別のドライブやボリュームをサービスがマウントするバージョンは、その場でのアップグレードにはならず、upgrade_not_hereでfailedになります。 - 取り消しとリバート。
up.Cancel(ctx)(またはapp.CancelInstanceUpgrade(ctx, key, id))は、待機中(インスタンスのスリープ待ち、またはバッチ内の順番待ち)のアップグレードを取り消します。cancelledになり、インスタンスは元のバージョンのままです(始まったものは 409upgrade_started)。up.Revert(ctx, glac.KeepDays(n))(またはapp.RevertInstanceUpgrade(ctx, key, id))は、アップグレードが保持していたもの(ディスク、アップグレード前の状態のドライブ(先に現在の中身のスナップショットを作る)、移行元のバージョン)にインスタンスを戻します。Kindがrevertの新しい*Upgradeで、アップグレードと同じように進み、待てます。戻り先がもう保持されていなければ、409rollback_goneで拒否されます。 - キーのバッチ。
app.UpgradeInstances(ctx, glac.BatchVersion("4"), glac.FromVersions("3"), glac.OnlyKeys(…), glac.WhenNow(), glac.KeepDays(n), glac.BatchConcurrency(8), glac.MaxFailures(1))は、アプリのキーを 1 つのバージョン(指定しなければアプリの現在のバージョン)へアップグレードします。それぞれインスタンスがスリープした時点で(WhenNowなら順番が来た時点で)、指定しなければ同時に 4 つ(1 つのノードでは 2 つ)ずつ行い、指定しなければ 5 回失敗した時点でfailedとして止まります。*UpgradeBatchを返します(Statusはrunning、done、failed、stopped。StopReason、Counts、Upgrades、Skipped、Origin)。batch.Wait(ctx)は、どう終わっても nil を返します(スリープしないインスタンスのメンバーがあるとバッチは動き続けるため、コンテキストの期限でwait_timeoutとして待機が終わります)。batch.Stop(ctx)は待機中のメンバーを取り消します。app.UpgradeBatches(ctx)、app.UpgradeBatch(ctx, id)、app.StopUpgradeBatch(ctx, id)で読み取りと停止を行います。 - キーのインスタンスのポート。
app.OpenInstancePort(ctx, key, "tcp", 5432, "2001:db8::/32")は、インスタンスがどこにあっても、キーのインスタンスが持つ専用のパブリック IPv6 アドレスで、指定した送信元(IPv6 のプレフィックスかアドレス。全員なら::/0)に対してポートを開き、接続先を含むOpenedPortを返します。app.InstancePorts(ctx, key, "tcp")はポートを一覧表示し、app.CloseInstancePort(ctx, key, "tcp", 5432)は 1 つを閉じて、開いていたかどうかを返します。UDP なら"udp"です。これらはそのサンドボックスのポートで(キー別インスタンス)、専用のアドレスのないインスタンスは拒否されます(409no_ipv6)。 - 複数をまとめて。
client.Deploys.Create(ctx, map[string][]glac.DeployOption{"api": {glac.Image("ghcr.io/acme/api:2")}, "web": nil})は、プロジェクトの複数のサービスを一度にデプロイします(プロジェクトのデプロイ)。それぞれにApp.Deployが受け付けるもの(nilならそのまま)を渡し、それぞれが待つものの順に進めてまとめて切り替え、デプロイを待ちます(glac.NoWait()なら待ちません)。置き換わったデプロイがあればそれを追います。失敗するとDeployとServiceを持つ*glac.DeployErrorになり、そのCode()はデプロイのもの(job_failed、job_timed_out、job_lostなど)です。これをアンラップすると、Paramがservices.<name>で型がdeploy_failedの*Errorになります。client.Deploys.GetとListで読み取ります。 - **コントロールプレーンの機能。**単独で動くノードに対しては、
client.Cubeのどの呼び出しも、そのノードの 404no_such_routeになります。
サンドボックス
sbx, err := client.Sandboxes.Create(ctx) // stays until deleted
if err != nil {
log.Fatal(err)
}
defer sbx.Delete(ctx)
res, err := sbx.Run(ctx, "python3 -c 'print(6*7)'") // res.Stdout, res.Stderr, res.ExitCode
if err != nil {
log.Fatal(err)
}
link, err := sbx.URL(3000)
if err != nil {
log.Fatal(err)
}
fmt.Println(res.Stdout, link)1 つの文字列で指定したコマンドは sh -c で実行されます。glac.Args(...) を使うと、プログラムとその引数として、そのまま実行されます。glac.Stdout(os.Stdout) は、Run が待っている間に出力をストリーミングします。sbx.Exec はすぐに戻り、cmd.Output(ctx) は届くそばから出力を読みます(io.Reader でもあります)。client.Sandboxes.Run は 1 つのコマンドのためのサンドボックスで、sbx.Run はサンドボックスでコマンドを 1 つ実行します。
| 呼び出し | 内容 |
|---|---|
client.Sandboxes.Run(ctx, cmd, …) |
1 つのコマンドのために作って実行し、削除するサンドボックス。Create とサンドボックスの Run のオプション |
client.Sandboxes.Create(ctx, Image(…), Name(…), Env(…), Metadata(…), Volumes(…), Drives(…), PublicPorts(…), SleepAfter(d), NeverSleep(), SleepNotice(d), SleepHoldMax(d), ExpiresAt(t), WithEgress(…), FromSnapshot(…)) |
サンドボックスを作成する。どのオプションも省略可能。起動時に始めるサービス:AutoStart(true)(イメージ自身の起動コマンド)、StartLine(…)、StartArgv(…) を、ReadyTCPOn(port)、ReadyHTTPOn(port, path)、ReadyCommand(…) とともに指定。Hostname(…)、StopSignal(…)、StopGrace(d)。ProjectNetwork() で最初からプロジェクトのプライベートネットワークにつなぐ(Info().ProjectAddress)。VolumeMount{…, Copy: true} は、イメージのそのパスにあるものを新しいボリュームに入れる(サンドボックスの作成) |
sbx.Info().AppID, VersionID, Key, ImageDigest |
コントロールプレーンで作ったサンドボックスはアプリのインスタンスである。イメージを指定せずに作った場合はプロジェクトのデフォルトのサンドボックスアプリ(sbx-sandbox)、それ以外はそのイメージのアプリ(アプリの Instances は、そのアプリのサンドボックスをそれぞれのキーの下に一覧表示する)。サンドボックスが属するそのアプリのバージョン、作成元のイメージ(その後移動したタグはアプリの新しいバージョンになり、それ以降に作ったサンドボックスはそちらに属する)、そこでのキー、名前または ID、ダイジェストで示すイメージ。作成のレスポンスとすべての読み取りで示され、保持される。テンプレートやスナップショットから作ったものと、フォークでは空 |
Create と Run の Init("systemd")。SandboxInfo.Init |
システム全体:イメージ自身の systemd がサンドボックスの PID 1 になる(Image を指定しなければ、systemd と OpenSSH 入りのプラットフォームの Ubuntu)。パッケージ、systemctl で起動するサービス、cron、ジャーナルが通常のマシンと同じように動き、専用のマシン ID を持ち、スリープ、復帰、移動を経ても保たれる。起動コマンドや準備完了のチェックとは併用できず(400 invalid_start)、FromSnapshot とも併用できない。SandboxInfo.Init は、systemd なら "systemd"、プラットフォームの init なら空 |
client.Sandboxes.Get, GetOrCreate, List(ctx, Status(…), MetadataIs(k, v)), ListPage(ctx, PageSize(n), After(cursor)) |
検索。検索または作成。一覧。1 ページ分 |
Create と sbx.Update の SuspendAfter(d)、WakeDailyAt("03:30")(DefaultSuspendAfter()、NoDailyWake() で元に戻す)。SandboxInfo.SuspendAfterMS、WakeDailyAt |
アイドルで停止した後、メモリを保存して本当にスリープするまで一時停止したままでいる時間(1 秒〜1 日。ノードは最大 10 分に抑える)と、休止中に、復帰を待つ自身の処理のために毎日復帰させる時刻(UTC)。アプリに指定した場合は、そのキー別インスタンスとステートフルなインスタンスの設定 |
Create と sbx.Update の OnExpiry("sleep")、HeldAsleep(true)。SandboxInfo.OnExpiry、HeldAsleep |
ExpiresAt の時刻が来たときの動作:サンドボックスを delete(デフォルト)、sleep(スリープさせて保持し、リクエストではいつもどおり復帰)、hold(同じく、スリープのまま保持)。そしてスリープ中にポートへのリクエストで復帰させるかどうか。スリープのまま保持されている間、プレビューアドレスは 502 sandbox_paused を返し、API の呼び出しでは復帰する |
sbx.Run(ctx, cmd, Args(…), Dir(…), Env(…), User(…), Timeout(d), Stdin(r), Stdout(w), Stderr(w)) |
実行して待つ。*Result は Stdout、Stderr、ExitCode、Duration、Usage、Wake を持つ |
sbx.Exec(ctx, cmd, StdinOpen(), TTY(cols, rows)), sbx.Terminal(ctx, …) |
コマンドを開始する。ターミナル(io.ReadWriteCloser) |
sbx.Files |
Read、Open、Write、WriteFrom、List、Stat、Exists、Mkdir、Move、Remove、そして SetAttributes(ctx, path, glac.FileAttributes{Mode, SizeBytes, ModifiedAt}):ファイルのモード、長さ、最終更新時刻 |
sbx.URL(port), sbx.Token(ctx, Scopes(…), ExpiresIn(d)) |
ポートへのリンク(ローカルで署名)。このサンドボックス用のトークン |
sbx.Info().IPv6, sbx.OpenPort(ctx, "tcp", port, from…), sbx.Ports(ctx, "tcp"), sbx.ClosePort(ctx, "tcp", port), Inbound(InboundPort{…}) |
専用のパブリック IPv6 アドレス(ある場合。なければ空)。指定した送信元(IPv6 のプレフィックスかアドレス。全員なら "::/0")に対して開いたポートと、その接続先。開いているポートの一覧。ポートを閉じる(開いていたかどうかを返す)。Create か Update に渡す一覧全体。受信はデフォルトで閉じており、開いたものはスリープ中も移動しても開いたまま。ネットワークを参照 |
sbx.RevokeToken(ctx, token) |
そのトークンだけがそれ以降拒否され、ほかのトークンはそれまでどおり使える。トークンそのもの(Token.Token)か、その ID(Token.ID、tok_…)で指定。1 つのサンドボックスで保持できる、期限の切れていない個別の無効化は 1,000 個まで(超えると 409 too_many_revoked_tokens。その場合は RevokeTokens を使う)。TokenID と ExpiresAt を持つ *TokenRevocation を返す |
sbx.RevokeTokens(ctx) |
それまでにこのサンドボックス用に発行したトークンがすべて使えなくなる(401 invalid_token)。プレビューリンクや Cookie の中のトークン、SSH セッションが持つトークンも含む。その後に作ったトークンは使える。API キーが必要。*TokenRevocation(SandboxID、Generation、RevokedAt)を返す |
sbx.Update, sbx.Sleep, sbx.Restart, sbx.Delete, sbx.Snapshot, sbx.Fork(ctx, n), sbx.Restore |
変更。スリープ。ディスクからの起動。削除。スナップショット。フォーク。復元 |
Create か Update に glac.Checkpoint(n)、Update に glac.NoCheckpoint()。Info().Checkpoint |
稼働中のチェックポイント(1〜600 秒間隔。0 なら 10 秒)。マシンが失われてもプロセスごと再開できる。解除。状況。チェックポイントを取れるマシンがなければ 409 checkpoints_unavailable |
Info().DiskWrites |
今日(UTC の 1 日)のディスクの書き込み量と、全速で書き込める 1 日の割り当て量(*SandboxDiskWrites):TodayBytes(うちチェックポイントのコピーがホストのディスクに書き込んだ量が CheckpointCopyBytes)、FullSpeedUntilBytes(割り当て量。ノードに別の指定がなければ 100 GiB。nil ならノードは何も減速しないが、数えることは同じ)、Limited と LimitedUntil(割り当てを超えると、その日が終わるまでディスクは毎秒 2 MiB で書き込みを受け付け、失敗する書き込みはない)。ディスクをオブジェクトストアにコピーしないノードでは nil で、何も数えない。ドライブへの書き込みはここでは数えない(ドライブへの書き込みに料金はかからない) |
client.Sandboxes.Snapshots.Get, client.Sandboxes.Snapshots.List(ctx, OfSandbox(id)), snap.Rename(ctx, name), snap.ExpireAt(ctx, t) |
スナップショット:ある瞬間のサンドボックス(メモリとプロセスを含む)。別の名前("" ならなし)、または自動で削除される時刻(ゼロ値なら削除しない) |
client.Sandboxes.SSHKeys.Create(ctx, publicKey, OfSandbox(…), ExpiresAt(t)), Get, List |
SSH キー:秘密鍵を持つ人は ssh <sandbox>@<gateway> で入れる。秘密鍵は、何かを送る前に拒否される |
ドライブ
ドライブは、サンドボックスより長く残るプロジェクトのディスクです。サンドボックスの作成時か実行中に、一度に 1 つのサンドボックスが読み書き可能でマウントし、サンドボックスがなくなると中身ごと保持され、次のサンドボックスがマウントできます。次のサンドボックスは同じリージョンのもの、またはマシンがホームのオブジェクトストアを読める別のリージョンのもの(後述)です。書き込まれるそばからリージョンのオブジェクトストアにコピーされるため、別のノード上のサンドボックスもマウントできます。その場合は先にそこへ運ばれます。課金されるのは書き込まれたものだけです(UsedBytes)。スナップショットはそのストア内のドライブのバージョンで、そのために何もコピーされません。フォークはスナップショットから作る新しいドライブ、復元はドライブをスナップショットの状態に戻すもので、いくつものサンドボックスがスナップショットを同時に読み取り専用でマウントできます(後述)。ドライブはコントロールプレーンの機能で(/v1/drives)、単独で動くノードに対しては、どの呼び出しもノードの 404 no_such_route を返し、そのノードのディスクはボリュームです(後述)。
client.Drives.Create(ctx, glac.Name("data"), glac.SizeBytes(10<<30), glac.InRegion("eu"))で、ファイルシステム以外は空のドライブを作ります。どのオプションも省略できます(SizeBytes:4 KiB ブロックの整数倍で最小 16 MiB。指定しなければ 64 GiB、無料プランでは 5 GiB。Durability("strict"):ゲストの fsync が、それ以前のすべての書き込みがオブジェクトストアに届いてから戻る)。Get、List、ListPage、Rename(ctx, drive, name)(空の名前なら名前なし)、Delete(ctx, drive)があります。client.Drives.Attach(ctx, sandbox, glac.DriveMount{Path: "/data", Drive: drive.ID})は、既存のサンドボックスにドライブを読み書き可能ですぐにマウントします(スリープ中のサンドボックスは復帰します)。Detach(ctx, sandbox, drive)はアンマウントし、プロセスが使っている間はForceDetachを使います。どれも*Driveを返し、そのInfo()はDriveInfoです(IDはvol-…(ドライブはボリュームでもある)、Name、SizeBytes、UsedBytes、AttachedTo、Region、Home、Status、Lease:唯一の書き込み元のノード、エポック、期限。キー別インスタンスのドライブではAppIDとKey。フォークではParentDriveIDとRootDriveID:フォーク元のドライブ(その後削除されている場合もある)と系統の最初のドライブで、フォークでないドライブでは空。データベースのドライブではManagedBy、それ以外では nil)。返されたドライブ自体もAttach、Detach、ForceDetach、Rename、Refresh、Delete、Snapshot、Snapshots、Fork、Restoreを持ちます。- データベースのドライブ(
Info().ManagedByがデータベースのID)を読み書き可能でマウントできるのはデータベースのインスタンスだけで、名前の変更、復元、削除はデータベースを通じて行います。ここでのそれらの呼び出しと、読み書き可能なマウントは拒否されます(409managed_by_database)。そのスナップショットとフォークはプロジェクトで取得でき、スナップショットは誰でも読み取り専用でマウントできます。データベースを構成するアプリも同じように示し(app.Info().ManagedBy)、そのUpdate、Deploy、Rollback、Deleteも同じく拒否されます。 - 新しいサンドボックスは、
client.Sandboxes.Create(使い捨てのRunではなく)にglac.Drives(glac.DriveMount{…})を渡してドライブをマウントします。アプリの唯一のインスタンスには、同じものをデプロイに渡します(多数のインスタンスやキーを持つアプリは拒否されます:409drive_single_writer。バージョンはドライブを読み書き可能でマウントし、スナップショットの読み取り専用のマウントはサンドボックス用なので、Snapshotを指定したマウントはそこでは拒否されます:400unknown_field)。キーを使うアプリのキーごとのインスタンスには、glac.KeyDrives(glac.KeyDrive{Name: "home", Path: "/home/app"})で専用のドライブを持たせます。 - ドライブは一度に 1 つのサンドボックスのものです。ほかのサンドボックスが持っているドライブは拒否され(409
drive_attached)、アタッチ中のドライブの削除も拒否されます。キー別インスタンスのドライブは、キーとともに削除されます(409key_drive)。 - 別のノードが保持しているドライブは、先にサンドボックスのノードへ運ばれます。オブジェクトストアがまだ現在の状態を保持していない間(503
copy_behind)や、運べなかった場合(503drive_not_brought)、呼び出しはRetryableです。クライアントはRetriesの指定どおりに再試行し、それでも失敗すればエラーを返すので、少し後に再度要求してください。 - リージョンをまたぐ場合(slice D9)。ドライブのホーム(
home)とは、そのコピーを保持するオブジェクトストアのリージョンで、作成されたリージョンです。別のリージョンのサンドボックスも、そのリージョンのマシンがホームのストアを読める場合はマウントできます(読めなければ 409not_on_one_machine)。ドライブはバージョンとして手放され、そこで引き継がれ、ゲストが読むのに合わせてホームのストアから読み取られ、ゲストが書き込むものは今いるリージョンのストアに送られます(region)。ホームは、そこに 1 時間いると追従します。client.Drives.MoveHome(ctx, drive)(drive.MoveHome(ctx))を使えばすぐに移ります。マシンがホームのストアに残っているものを自分のストアにコピーし、何も残らなくなった時点でhomeが新しいリージョンになります。DriveInfo.HomeMoveが移動の進み具合を示します(asked_at、asked_by、copied_objects、copied_bytes、objects_left、error)。古いホームのコピーは、保持しているどのバージョンも必要としなくなった時点で消えます(1 日後)。ドライブのホームが移るのは最大で 6 時間に 1 回で(409home_moved_recently)、ホームが現在のリージョンにあるドライブでは 409home_hereになります。 - プランの制限:無料プランでは最大 10 GiB のドライブを 3 つ(合計 15 GiB)、有料プランでは最大 1 TiB のドライブを 500 個です(403
drive_limit_reached)。 glac.OfDrive(id)、glac.OfKind("drive")、glac.GroupBy("drive")は、ドライブが保持した量、書き込まれた量、キャッシュ外から読まれた量を報告します。イベントdrive.created、drive.deleted、drive.attached、drive.detachedは、EventDriveかEventDriveAttachedにデコードされます。- スナップショット。
client.Drives.Snapshot(ctx, drive, glac.Name(…), glac.FSConsistent())(またはdrive.Snapshot(ctx, …))は、ドライブのスナップショットを取り、*DriveSnapshotを返します。オブジェクトストア内に保持されるドライブのバージョンで、何もコピーされません。実行中のサンドボックスが読み書き可能で持っているドライブは、ゲストの書き込みを短時間(最大 10 秒。超えるとRetryableの 503unavailable)止めて取ります。glac.FSConsistent()を指定すると、サンドボックスのエージェントがファイルシステムを凍結します(Consistencyはfrozen。エージェントが凍結できなければ 409not_frozenなので、指定せずに取ってください)。指定しなければマシンを一時停止します(paused。停電時と同じ状態)。実行中のサンドボックスが持っていないドライブはat_restです。ノードがオブジェクトストアに何もコピーしないドライブにはスナップショットはありません(409not_copied)。Snapshots(ctx, drive)はドライブのスナップショットを新しい順に、client.Drives.AllSnapshots(ctx, "")はプロジェクトの全ドライブのスナップショット("true"ならその後削除されたドライブのものだけ)を一覧表示します。GetSnapshot(ctx, drive, snapshot)は 1 つを取得し(404snapshot_not_found)、DeleteSnapshot(ctx, drive, snapshot)は 1 つを削除します。*DriveSnapshotはRefresh、Delete、Fork、Restore、Attach、Detach、ForceDetachを持ち、そのInfo()はDriveSnapshotInfoです(IDはdsnap-…。DriveID、Name、Consistency、UsedBytes:取得時にドライブが保持していた量。ExclusiveBytes:単独で保持する量。ExclusiveAt、Version、CreatedAt)。 - **スナップショットはドライブより長く残ります。**ドライブの削除後も、ドライブの ID で一覧表示、読み取り、フォーク、読み取り専用でのマウントができます。単独で保持する量(
ExclusiveBytes)に対して、1 時間ごとに、ドライブのデータの料金(1 GB-月あたり $0.02)で課金されます。 - フォーク。
client.Drives.Fork(ctx, drive, glac.Name(…), glac.FromSnapshot(snapshot))(またはdrive.Fork、snap.Fork(ctx, glac.Name(…)))は、スナップショット、またはドライブの現在の状態を最初のバージョンとする新しいドライブを作ります。何もコピーされず、すぐにマウントできます。新しいドライブを返し、そのParentDriveIDとRootDriveIDが作成元を示します。作成と同じく、プランのドライブ数の上限の対象です(403drive_limit_reached)。フォークは、ほかのドライブと同じく、UsedBytes、つまり論理的な内容全体で課金されます。10 GB のスナップショットのフォークは、10 GB のドライブとして課金されます。 - 復元。
client.Drives.Restore(ctx, drive, snapshot)(またはdrive.Restore(ctx, snapshot)、snap.Restore(ctx))は、ドライブの最新のバージョンの後に、スナップショットの内容を持つ新しいバージョンを書き込みます。その間のバージョンは、スナップショットかフォークが保持している限り残るため、古いスナップショットに復元した後に新しいスナップショットに復元することもできます。サンドボックスが読み書き可能で持っているドライブは拒否されます(409drive_attached)。先にデタッチしてください。 - **バージョンのウィンドウ。**作成時の
glac.KeepHistory(d)、client.Drives.SetHistory(ctx, drive, d)(0 でオフ)、Versions(ctx, drive)とVersionAt(ctx, drive, t)(DriveWindowVersion)、glac.ForkAt(t)、client.Drives.RestoreTo(ctx, drive, t)(とdrive.SetHistory、drive.Versions、drive.RestoreTo。DriveInfo.HistorySeconds、History):ドライブのバージョンのウィンドウ(slice DB8)で、時刻を指定して、どこまで遡って復元またはフォークできるかです。3600〜86400 秒(指定しなければなし。オフにすると、保持していたものは消えます)。書き込みがあった 30 秒ごとに、ある時点のドライブであるバージョンが 1 つウィンドウに加わり、それらが単独で保持するものは、スナップショットと同じく課金されます。時刻を指定した復元やフォークでは、その時刻以前の最新のバージョンが使われます。その時刻を指定してバージョンの一覧を呼び出すと、そのバージョンが示されます。 - **ノードの NVMe 上のキャッシュ。**作成時の
glac.CacheBytes(n)、client.Drives.SetCache(ctx, drive, n)とdrive.SetCache(ctx, n)(全量ならglac.CacheAll)、drive.CacheBytes()とDriveInfo.CachedBytes:ノードが NVMe に保持するドライブの最大量です。指定しなければ全量(ドライブのサイズ)です。0 まで減らせ、それを超えた分はオブジェクトストアだけにあり、ゲストが読むとそこから読み取られます(最も長く読まれていないものから手放し、ストアにまだないものは手放しません)。キャッシュは、ドライブが保持するデータとは別に、埋まっている量に応じて 1 時間ごとに課金されます。小さくすると、超えた分はストアが保持した時点で手放されます(実行中のサンドボックスが全量キャッシュでマウントしたドライブでは、そのサンドボックスが次にスリープまたは停止した時点から)。大きくすると、それ以降にゲストが読んだものを保持します。API ではドライブをボリューム(/v1/volumes)と呼び、クライアントは/v1/drivesでアクセスします(以前と同じように応答します)。コントロールプレーンがキャッシュについて何も示さない場合、CacheBytes()はドライブのサイズです。CachedBytesは、現在ノードの NVMe にある量です(どのノードも保持していなければ nil)。UsageGroupとUsageReportTotalsにはCacheGBHoursがあります。 - 読み取り専用のマウント。
glac.DriveMount{Path: "/snap", Drive: drive.ID, Snapshot: snap.ID}(mode: "snapshot"を送ります)は、スナップショットを読み取り専用でマウントします。サンドボックスの作成時にglac.Drives(…)に渡すか、実行中にclient.Drives.AttachSnapshot(ctx, sandbox, mount)(snap.Attach(ctx, sandbox, path))に渡します。DetachSnapshot(ctx, sandbox, snapshot)とForceDetachSnapshotは、スナップショットの ID でマウントを外します。どれもスナップショットを返します。ドライブのリージョンのどのマシン上でも、ドライブを誰が持っていても、ドライブが削除された後でも、いくつものサンドボックスが同時にマウントできます。ブロックはゲストが読むのに合わせてオブジェクトストアから届きます。このキャッシュ外の読み取りに料金はかからず、使用量ではそのサンドボックスの下に表示されます(client.GetUsageReport(ctx, glac.OfSandbox(id))のDriveColdReadBytes)。そのサンドボックスのマシンがすでに保持しているものの読み取りにも料金はかかりません。ゲストは書き込めず、それをマウントしたサンドボックスは別のマシンへ移動しません。AttachはSnapshotを指定したマウントを、AttachSnapshotは指定しないマウントを受け付けず、DetachSnapshotはdsnap-…以外の ID を受け付けません。いずれも何かを送る前に拒否されます。
client.Volumes は API の /v1/volumes で、ドライブの下にあるディスクです。移行のために残されています。これにしかないのは、ディスクがボリュームである単独で動くノードと、複数のサンドボックスが同時にマウントするファイルシステムである共有ボリューム(glac.Shared())です。コントロールプレーンは、プロジェクトのキーに対して通常のボリュームを作りません。client.Volumes.Create(ctx, glac.Name("team"), glac.Shared())、Get、List、vol.Delete(ctx)(サンドボックスがまだ持っているボリュームは残り、エラーになります)があります。ボリュームは glac.Volumes(glac.VolumeMount{Path: "/team", Volume: vol.ID}) でマウントし、client.Sandboxes.Create か sbx.Update、またはアプリに渡します。アプリの場合はインスタンスがマウントします。
**ボリュームのバックアップ。**バックアップは、ある瞬間のボリューム(ドライブもボリュームです)のコピーで、オブジェクトストアに、期限が来るまで保持されます。呼び出しによって、ボリュームのルールに従って毎日、またはサービスの新しいバージョンがインスタンスを置き換える前に取得されます。ドライブのスナップショットと違い、それ自体が独立したコピーで、それだけからボリュームを作ることができ、元のボリュームより長く残ります。ボリュームのバックアップは前回以降に変わったものだけを保持し、複数のバックアップが必要とするブロックは、そのうち最も古いもので 1 回だけ課金されます。ストアがすべてを受け取るまでは making、その後は ready で、それ以降はストアが保持する量(StoredBytes)に応じて、スリープ中のサンドボックスが保持するものと同じ料金で課金されます(バックアップ)。バックアップはコントロールプレーンの機能です。
client.Volumes.Backup(ctx, "data", glac.ExpiresInDays(7))(またはvol.Backup(ctx))は、今すぐバックアップを取り、*Backupを返します。指定した日数(1〜365)、またはボリュームのルールの日数(設定しなければ 30 日)保持されます。client.Volumes.Backups(ctx, "data")は、ボリュームのバックアップを新しい順に一覧表示します(削除済みのボリュームのものは、その ID で)。オブジェクトストアに何もコピーしないノードにはバックアップはありません(409not_copied)。client.Backups.List(ctx)は、削除済みのボリュームのものを含め、プロジェクトのバックアップを新しい順に一覧表示し、ListOf(ctx, volumeID)は 1 つのボリュームのものを一覧表示します。Get(ctx, id)、Delete(ctx, id)(それ以降は課金されず、そこから作ったボリュームは残ります)、そしてRestore(ctx, id, glac.Name("data-back"))は準備ができたバックアップから新しいボリュームを作り、client.Volumes.Create(ctx, glac.FromBackup(id))と同じです(作成中は 409backup_not_ready、失敗後は 409backup_unusable)。*BackupはBackupInfoのフィールド(IDはbak-…。VolumeIDと、その時点のボリュームの名前であるVolumeName。Status:making、ready、failed。Reason:manual、daily、before_version。Consistency:frozen、crash。FrozenMS:ボリュームの書き込み元がコピーのために待った時間。SizeBytes:ボリュームが保持していた量、VolumeSizeBytes:保持できた最大量で、そこから作るボリュームが保持する量。StoredBytes:課金の基準。OwnBytes:削除すると減る量。SharedBytes。Shared、Region、Failure、CreatedAt、課金が始まるReadyAt、ExpiresAt)と、専用のRefresh、Restore、Deleteを持ちます。- バックアップから作るボリュームは、バックアップ元のボリュームと同じサイズと種類で(
glac.FromBackupではglac.SizeBytesとglac.Sharedを指定しません)、バックアップのリージョンに作られます。Statusは、バックアップ全体を保持するまではrestoring、その後はreadyで、それまではアタッチできません。FromBackupがバックアップを示します。配置先のマシンで復元できない場合、コントロールプレーンはリージョンの別のマシンにもう一度作ります。そのときRestoreAttemptは 2 になり、FirstFailureが最初の試行に失敗した理由を示します。それも失敗するとfailed(Failure)になり、削除しかできません。 glac.OfBackup(id)、glac.OfKind("backup")、glac.GroupBy("backup")は、バックアップが保持した量を、状態の計測項目(state_gb_hours)で報告します。client.GetBilling(ctx)のMeters.State.BackupsGBHoursは、その計測項目のうちバックアップの分を示します。
ドメイン
プロジェクトのドメインは、デフォルトのアドレスと同じくアプリへ、またはサンドボックスのポートへ向かう名前です。ドメインはコントロールプレーンの機能です。
| 呼び出し | 内容 |
|---|---|
client.Domains.Create(ctx, domain, glac.ToApp(…)) または glac.ToSandbox(id, port)(glac.Proxied(…) を指定可能)。Get、List(ctx, glac.OfApp(…))、Delete。d.Update(ctx, …)、d.Refresh、d.Delete |
アプリまたはサンドボックスのポートのための名前。Info().Verification.Records のレコードが DNS に現れるまでは pending_verification(独自ドメイン)。プロジェクトにすでにあれば 409 domain_exists |
ブラウザ
**未公開。**Glac のブラウザはまだ利用できません。以下は公開に先立つ、現時点での SDK です。
セッションは Glac がホストする Chromium で、Chrome DevTools Protocol(CDP)のクライアントが、その CDPURL(Playwright の connectOverCDP や Puppeteer の browserURL に渡すアドレス)から外部で操作します。クライアントの接続中は稼働し、最後のクライアントが離れると数秒後に、ページを保持したままスリープします。アドレスには認証情報が含まれるため、セッションを表示するときにはアドレスは含まれません。
session, err := client.Browsers.Create(ctx, glac.BrowserName("agent-42"))
if err != nil {
return err
}
defer client.Browsers.Delete(ctx, session.ID)
fmt.Println(session.CDPURL) // where a CDP client connects; the credential is in itclient.Browsers.Create(ctx, opts...)は稼働中のセッションを作ります。glac.BrowserKind("chromium")(画面付き。デフォルトはchromium-headless。glac.BrowserKind("lightpanda"):レイアウトエンジンのないブラウザであるlightpanda)、glac.BrowserName、glac.BrowserRegion、glac.BrowserSleepAfter、glac.BrowserConnectionIdle、glac.BrowserDeleteAfterIdle、glac.BrowserMetadata、glac.BrowserProfile(name, save)とglac.BrowserProfileVersion(name, version, save)(セッションを返す前に読み込むプロジェクトのプロファイル。saveなら削除時に保存し直す)、glac.BrowserProxy(url)(自前の HTTP プロキシ。有料プランのみ。後述)を指定できます。既存のセッションの名前を指定すると、そのセッションがページとともに復帰して返されます。実行前にサンドボックスが失敗したものはセッションにならず、作成は 503session_failedで拒否されます。client.Browsers.Get(ctx, idOrName)、Delete(ctx, idOrName)(保存するプロファイルを指定して作ったセッションは、先にプロファイルを保存)、DeleteWithoutSavingProfile(ctx, idOrName)があります。*BrowserSessionは、ID、Kind、Status、CDPURL(Playwright と Puppeteer のアドレス)、LiveURL、Profile(作成時に指定した、または最後に保存したもの:Name、Save、Version)、Proxy(自前のプロキシのURLとUsername。パスワードは含まない)、各種の時刻、Usage(AwakeSecondsと、プロキシを双方向に通過した量ProxyBytes(ProxySentBytes、ProxyReceivedBytes))を持ちます。- 自前のプロキシ(
glac.BrowserProxy("http://user:password@proxy.example.com:3128")。CONNECTを受け付ける HTTP プロキシ):セッションのポート 80 と 443 への接続は、ブラウザの隣にあるリレーによってそこを経由して送信され、ブラウザには何も知らされません。認証情報はプラットフォームが保持します。無料プランでは 403proxy_not_on_planです。自前のプロキシを参照してください。 session.Statusは、awake、asleep、unavailable(ノードに到達できない)、failed(作成に応答した後でサンドボックスが失敗した。たとえばブラウザが停止して戻らなかった)のいずれかで、失敗した場合はsession.Errorが理由を示します(*BrowserError:ノードが返したとおりのCode、Message。失敗していなければnil)。イベントbrowser.failedもそれを伝え、そのデータはEventBrowserFailed(BrowserID、Name、Kind、Error.Code)にデコードされます。
セッションは、ほかのインスタンスと同じく、使用したキューブのリソースで課金されます。処理している間の CPU、稼働中のメモリ、送信トラフィックです(料金とプラン)。session.Usage.AwakeSeconds は稼働していた時間です。
一覧表示、変更、スリープ、新しいアドレスの発行は、Python と TypeScript の SDK と glac browsers にあります。セッションはコントロールプレーンの機能です。
データベース
データベースはマネージド Postgres です。ドライブ上で動く専用の PostgreSQL で、何も要求がないときはスリープし、接続があればセッションを保ったまま復帰します。オーナーのパスワードは Create と ResetPassword のレスポンスにしか含まれず、どこにも保存されません。そのどちらかが返した *Database の ConnectionString() には、パスワードが含まれます。
db, err := client.Databases.Create(ctx, "shop", glac.DatabaseVersion("18"))
if err != nil {
return err
}
conn, err := pgx.Connect(ctx, db.ConnectionString()) // from a sandbox or a service of the projectclient.Databases.Create(ctx, name, opts...)は、データベースを作成し、最初の起動を待ちます(Statusはready、またはcreating。その場合は準備ができるまでGetしてください)。glac.DatabaseVersion、glac.DatabaseRegion、glac.DatabaseInCluster(クラスター内のデータベースの名前。glacdb)、glac.DatabaseSizeOf(vcpus, memoryBytes)、glac.DatabaseStorageOf(sizeBytes, durability)(デフォルトのstrict、またはstandard)、glac.DatabaseSleepAfter、glac.DatabaseSuspendAfter(メモリを保存して本当にスリープするまで一時停止したままでいる秒数。その間の接続には 1〜2 ミリ秒で応答する。1〜86400 秒、デフォルトは 300 秒)、glac.DatabaseWakeDailyAt("03:30")(休止中に毎日その時刻に復帰させる。pg_cronのジョブは、いずれにせよそれぞれの時刻に復帰させる)、glac.DatabaseMetadataを指定できます。既存のデータベースの名前を指定すると、パスワードなしでそのデータベースが返されます。client.Databases.SetSuspendAfter(ctx, idOrName, n)とSetWakeDailyAt(ctx, idOrName, "04:00")は、この 2 つを全ブランチまとめて変更し、0と""で元に戻します(300 と、なし)。無料プランでは、Neon の無料プランがゼロまでスケールするのと同じく、データベースの休止の設定は固定です。最後のクエリの 1 秒後に一時停止し(sleep_after_secondsは 1)、その 5 分後にスリープします(suspend_after_secondsは 300)。ほかの値は、作成でも変更でも 400invalid_fieldで拒否されます。client.Databases.CreateBranch(ctx, idOrName, name, glac.BranchParent("main"), glac.BranchExpiresAt(t))は独自のブランチを作ります。親(指定しなければmain)の現在の状態を、何もコピーせずに引き継ぎ、プロジェクトのネットワーク上の<database>-<name>に専用の PostgreSQL、エンドポイント、ドライブを持ちます。有効期限を指定すると、その時刻に自動で削除されます。ロールとパスワードは親のものです:branch.ConnectionString(ownerPassword)。DeleteBranch(ctx, idOrName, branch)は PostgreSQL を止めてドライブを削除します。main(409root_branch)や、ほかのブランチの作成元になったブランチ(409has_branches)は削除できません。- 作成時の
glac.DatabaseHistorySeconds(n)、client.Databases.SetHistory(ctx, idOrName, n)、client.Databases.Restore(ctx, idOrName, t, glac.Exactly())、glac.BranchAt(t)、glac.BranchAtExactly(t)(Database.HistorySeconds、History):履歴(slice DB8 と DB5)で、時刻を指定して、ルートブランチをどこまで遡って復元できるか、またはブランチを作れるかです。指定しなければ 1 日で、有料プランでは 0(なし)〜30 日、無料プランでは 1 日です。復元はルートブランチをその場で戻します。分ちょうどの時刻やバージョン自体の時点なら、その時刻以前で最新の、ドライブのウィンドウのバージョンへ(書き込みがあった 30 秒ごとに 1 つ、最大 1 日分)。それより前や秒単位の時刻、またはglac.Exactly()を指定した場合は、WAL アーカイブによってその時点そのものへミリ秒単位で戻します(WAL をその時点まで再生します。数秒〜数分かかり、呼び出しは待ちます)。エンドポイント、接続文字列、オーナーのパスワードは変わらず、接続は切断され、復元前の状態は独自のブランチmain_old_<the restore's moment>として保持されます。新しいバージョンが 5 分以内に応答しなければ取り消されます(503database_restore_failed)。時刻を指定したブランチは、代わりにその時点から作られます(from: {at, exact})。履歴にない時刻は 400invalid_historyになり、そのメッセージは、ウィンドウとアーカイブがいつから遡れるかを示します。秒単位の時刻(またはexact)はアーカイブから戻すか拒否され、その前のウィンドウのバージョンが使われることはありません。アーカイブが届かない場合(アーカイブを保持しないデータベース、または最も古いベースより前の時刻)は 400invalid_history、アーカイブのストアがセグメントを拒否している間は 503database_archive_unavailable(再試行可能)です。どの拒否も、その時刻以前のウィンドウのバージョンを示すので、代わりにそのバージョン自体の時点を指定できます。ストアがブロックを返さない場合は 503drive_unreadable(再試行可能)で拒否され、何も作られません。オブジェクトストアの障害が長引き、ドライブがログのために保持できる量を超える WAL が待つことになると、データベースを動かし続けるためにその WAL は手放されます。これがアーカイブの欠落で、History.Gaps(DatabaseHistoryGap:From、To、FromLSN、ToLSN)に示されます。手放した WAL の開始時刻、アーカイブがどの時刻も復元できない期間の終わり(その後に取った最初のベースの終わり。それまでは null)、ログ内での開始位置と終了位置です。欠落の間の時刻は、ドライブのウィンドウからしか復元できず(分ちょうどの時刻、またはバージョン自体の時点)、秒単位や exact では 400invalid_historyになります。欠落はイベントでも伝えられます。最初に見つかったとき(データベースの稼働中に、欠落ごとに 1 回)にdatabase.history_gap、その後アーカイブが再び復元できるようになったときにdatabase.history_resumedです。event.Decode(&gap)は、それらのデータをEventDatabaseGapに読み込みます。データベース、欠落のFrom、To(前者では nil)、FromLSNとToLSN、Segments(手放した 16 MB のセグメントの数)、そして前者ではError(オブジェクトストアの最後の拒否の内容)です。 - 作成時の
glac.DatabaseTiered()とclient.Databases.SetTiering(ctx, idOrName, on)は、階層型ストレージのオンとオフを切り替えます(slice DB18:有料プランのみ。そのために各ブランチの PostgreSQL が 1 回再起動します)。Database.Tieringは、オンかどうかと、現在の課金の基準(TieredBytes)を示します。 Get(ctx, idOrName)、List(ctx[, name])、Delete(ctx, idOrName, finalSnapshot)(finalSnapshotが false でなければ、ドライブのスナップショットを 7 日間保持)、Branches(ctx, idOrName)(最初にmain、次に独自のブランチ)、Branch(ctx, idOrName, "main")、SleepとWake(ブランチをすぐに)、ResetPassword(ctx, idOrName, role)(新しいパスワードはこのレスポンスにだけ含まれる。""はデータベースのオーナー)があります。client.Databases.Roles(ctx, idOrName)は、ルートブランチのログインするロールを、PostgreSQL 自体から読み取って一覧表示します([]DatabaseRole:Name、Owner)。オーナーと、作成したロール(CREATE ROLE … LOGIN)で、プラットフォームのロールは含みません。ResetRolePassword(ctx, idOrName, role)は、そのどれかに新しいパスワードを与え、それはこのレスポンスにだけ含まれます。ロールのPasswordと、そのロールでのルートブランチの接続文字列(ConnectionString())を持つ*DatabaseRoleSecretです。オーナーの接続文字列は、API が返すデータベースから作られます。独自のブランチは、作成時のパスワードを保持します。db.ConnectionString()とbranch.ConnectionString(password):libpq、pgx、database/sqlのドライバーに渡せるもので、API が返す場合はパブリックなもの、そうでなければプロジェクトのネットワーク上のものを、パスワード(パーセントエンコード)入りで返します。db.DefaultBranchはConnectionURI、PooledURI、PrivateURI、Endpoint、Stateを持ちます。
データベースには、プロジェクトのネットワーク上で、そのサンドボックス(project_network で作成)とサービスから名前でアクセスします。これが private_uri です。エッジが PostgreSQL を提供する場合は、パブリックアドレスでどこからでもアクセスできます(connection_uri、ポート 5432、TLS のみ。プーラーは pooled_uri)。提供するエッジがない場合や、データベースに名前を付けるリージョンがない場合は nil で、接続文字列は、それらがあればそれらを使います。データベースとブランチを表示するとき、パスワードは含まれません。データベースはコントロールプレーンの機能です。
マネージドアプリケーション
カタログのアプリケーション(たとえば Rivet)は、プロジェクトに専用のキューブのリソースとしてインストールされます。アプリ、ボリューム、シークレット、バケットで、インストールのラベルが付き、変更はインストールを通じてのみ行い、それぞれのリソースとして課金されます(マネージドアプリケーション)。インストールのレスポンスには、秘密のもの(管理者トークン、それを含むエンドポイント)も含め、すべての出力値があり、読み取りでそれらが表示されるのは admin スコープを持つキーだけです。インストールのオブジェクトは、以前のレスポンスが返し、後のレスポンスが隠した出力値をそれぞれ保持します。
rivet, err := client.Catalogue.Get(ctx, "rivet", "") // its parameters, and a month of it in Cube's meters
engine, err := client.Installations.Create(ctx, "rivet", glac.InstallationCreate{Parameters: map[string]any{"disk_gib": 20}})
fmt.Println(rivet.Calculator.Month, engine.Info().Outputs["endpoint"]) // RIVET_ENDPOINT, its token in it| 呼び出し | 内容 |
|---|---|
client.Catalogue.List(ctx), client.Catalogue.Get(ctx, app, version) |
カタログのアプリケーションの一覧。それぞれ CatalogueApp(App、Version、Title、Summary、Verified、Licence、Versions、Parameters:JSON Schema、Outputs、Month を含む Calculator)。1 つのアプリケーション(最新バージョン、または指定したもの。"" なら最新)と、その Definition |
client.Installations.Create(ctx, app, glac.InstallationCreate{Name, Version, Region, Parameters, Requires, NoWait}) |
インストールし、準備ができるまで待つ(NoWait ならすぐに戻る)。失敗すると *InstallationError(Installation 付き)になり、アンラップするとコード installation_failed の *Error になる。先にコンテキストの期限が過ぎた場合は wait_timeout |
client.Installations.List(ctx, app), client.Installations.Get(ctx, idOrName) |
プロジェクトのインストールの一覧(新しい順。app が "" ならすべて)。1 つのインストール |
inst.Update(ctx, glac.InstallationUpdate{Version, Parameters, NoWait}), inst.Delete(ctx), inst.Refresh(ctx), inst.Wait(ctx) |
別のバージョンへの変更、またはパラメーターのマージパッチによる変更(nil の値でデフォルトに戻す)。構成するものごとの削除(Status():deleted または deleting) |
inst.ID(), Name(), Status(), Info() |
API が返すとおり:Info() は Outputs、SecretOutputs、Parameters、Apps、Volumes、Buckets、Requires、Failure を持つ |
マネージドアプリケーションはコントロールプレーンの機能です。
シークレットと共有変数
client.Secrets.Put(ctx, "DB_URL", value, glac.AllowedHosts("db.example.com"))は、API が二度と返さない値と、それを送ってよいホストを保持します。client.Secrets.Update(ctx, name, hosts...)はホストだけを変更します。List、Deleteもあります。ほかのホストに送ることになる呼び出しは、403secret_host_not_allowedで拒否されます。client.Variables.Put(ctx, "REGION", "eu")、List、Delete:プロジェクトの共有変数で、アプリのEnvから"${{ shared.REGION }}"として参照します。
プロジェクト、アカウント、請求
プラットフォーム自体の呼び出しはクライアントのメソッドです。client.GetProject と client.ListEvents(ctx, OfType(…))、client.GetAccount と client.UpdateAccount(ctx, EgressOverageCap(n))、client.GetUsage と client.GetUsageReport(ctx, Start(t), GroupBy(…))、client.GetBilling、client.UpdateBilling(ctx, Plan("paid"))、client.GetBalance、client.UpdateBalance(ctx, AutoReload(true))、client.TopUp(ctx, 20)、client.ListCharges、client.ListLedger です。プロジェクト、そのイベント、請求はコントロールプレーンの機能です。
**イベントのデータ。**コントロールプレーンのイベントの種類ごとに、そのデータの構造体がこのパッケージにあり、説明のスキーマにちなんだ名前が付いています。e.Decode(&v) で読み込みます(var made glac.EventDatabase; err := e.Decode(&made))。データベースのもの:glac.EventDatabase(database.created:region と PostgreSQL の version 付き。database.deleted:7 日間保持されるドライブのスナップショット final_snapshot_id 付き)、glac.EventDatabaseBranch(database.branch_created:parent 付き。database.branch_deleted:reason 付き)、glac.EventDatabaseRestored(database.restored:時点 at と、復元前の状態を保持するブランチ old_branch_id)、glac.EventDatabaseArchive(database.archive_failing:since、連続して失敗したセグメントの数 failures、その間に復元で遡れる範囲 archived_until、オブジェクトストアの error。database.archive_recovered:recovered_at)、glac.EventDatabaseGap。ほかも同様です。サンドボックスのもの(glac.EventSandboxSlept、glac.EventSandboxWoke、glac.EventSandboxMoved、glac.EventSandboxDeleted など)、アプリとそのキーのもの(glac.EventApp、glac.EventAppFailed、glac.EventKeyCreated など)、プロジェクトのデプロイとキー、バックアップ、ドメイン、エクスポート先、ドライブのスナップショットのもの(glac.EventProjectDeployed、glac.EventBackup、glac.EventDomain、glac.EventDestination、glac.EventDriveSnapshot など)、そしてアカウントのプラン、チャージ、返金、撤回、残高、クレジット、ストレージ、送信量の上限、利用上限額、保留、未払いのもの(glac.EventSubscriptionPeriod、glac.EventTopupCollected、glac.EventWithdrawalReceived、glac.EventBalance、glac.EventInDebt など)です。その種類のすべてのイベントにあるわけではないフィールドや、null のフィールドはゼロ値になります(ゼロが別の意味になる場合はポインター)。
Webhook、API キー、利用上限額、プロジェクト。client.Webhooks.Create(ctx, url, glac.WebhookEvents(…), glac.WebhookEnabled(…)) は、プロジェクトのイベントを自前のアドレスに送ります(各配信に署名する Secret は、このレスポンスにだけ含まれます)。Get、List、Update(ctx, id, glac.WebhookURL(…)…)、Delete もあります。client.Keys.Create(ctx, glac.ProjectKeyName(…), glac.ProjectKeyScopes(…), glac.ProjectKeyExpiresAt(t)) は API キーを作ります(キーそのもの Key は、このレスポンスにだけ含まれます)。Get、List、Delete もあります。client.Limits(ctx) と client.UpdateLimits(ctx, glac.SpendLimit(50))(glac.NoSpendLimit())は、プロジェクトの利用上限額と今月の支出額で、sbx.Limits と sbx.UpdateLimits はサンドボックス自体のものです。client.RequestLimit(ctx, limit, wanted, why) は、アカウントの申請による上限の引き上げを 1 つ申請します(名前で指定する上限、"volumes"、"volume_bytes"。バイト数の 2 つはバイト単位。同じ上限の申請が待機中なら 409 limit_request_pending)。client.ListLimitRequests(ctx, glac.PageSize(n), glac.After(cursor)) と client.LimitRequest(ctx, id) は、申請をオペレーターの回答とともに読み取ります(*LimitRequest:Status は pending、granted、refused。Granted、Answer)。instance.restarted、instance.upgraded、instance.reverted、instance.upgrade_failed、limit_request.granted と .refused のイベントのデータは、EventInstanceRestarted、EventInstanceUpgraded、EventInstanceReverted、EventInstanceUpgradeFailed、EventLimitRequest にデコードされます。サンドボックス(とインスタンス)の Info().StartCommand は、起動コマンドの実行状況、マシン内で再起動された回数、最後の終わり方を示します。client.UpdateProject(ctx, glac.DeleteAfterIdleDays(30))(glac.NeverDeleteIdle())は、スリープが何日続いたらサンドボックスを削除するかを設定します。コントロールプレーンの機能です。Webhook と API キー、プロジェクトの上限の設定、UpdateProject には admin スコープを持つキーが必要で、サンドボックスの上限の設定には write が必要です。
ログのエクスポート先、監査ログ、請求関連の書類。client.Destinations は、プロジェクトのアプリのログ(とメトリクス、リクエストのトレース:glac.DestinationSignals("logs", "traces"))のエクスポート先(OpenTelemetry のエンドポイント)です。Create(ctx, name, glac.DestinationEndpoint(u), glac.DestinationHeaders(h))(作成時にすぐ 1 件のレコードで試す:Status.Connected)、Get、List、Update、Delete、Test(すぐに 1 件送る)があります。ヘッダーの値は認証情報で、エクスポート先の作成時か変更時に送られ、どのレスポンスにも含まれません(返されるのはヘッダーの名前だけです)。client.ListAudit(ctx, glac.PageSize(n)) は、プロジェクトの監査ログの 1 ページ分を新しい順に返します(実行者、メソッド、パス、ステータス)。読み取り以外のすべての呼び出し(拒否されたものも含む)と、オペレーターによるアプリのログの読み取りすべてです。client.GetStatement(ctx, "2026-09") は 1 か月の明細(“” なら今月)で、データベースごとの行(Databases:その月の使用量、履歴と階層化データを別記したもの、それを定価で換算した額)を含みます。client.ListInvoices(ctx) は Stripe にある請求書(PDF のリンク付き)、client.ListNotices(ctx) はアカウントに送られたメール、client.ListWithdrawals(ctx) は今撤回できる購入と行った撤回(EEA または英国の消費者は、購入から 14 日以内であれば撤回できます)、client.Withdraw(ctx, chargeID, name, email) は購入者自身による撤回の意思表示で、すぐに受理されます。コントロールプレーンの機能です。エクスポート先の作成、変更、テスト、削除、監査ログの読み取り、撤回には admin スコープを持つキーが、それ以外には読み取りのできるキーが必要です。
bill, err := client.GetBilling(ctx)
if err != nil {
log.Fatal(err)
}
cpu := bill.Meters.CPU
fmt.Println(bill.Plan, cpu.Used, cpu.Unit, "used") // free 7.5 cpu_seconds usedアカウントの Email は通知の送信先で、glac.AccountEmail(address) で設定します。EmailVerified は確認済みかどうか(メールが送られるのは確認済みのアドレスだけで、そうでないアドレスには先にリンクが送られます)を、EmailUndeliverable(*EmailUndeliverable:Why、Since、Detail)はそのアドレスへのメールが不達だったことを示し、その間、通知は保留されます(通知の送信先)。アカウントの Language は通知の言語です(NoticeLanguage:Code は “en”、“de”、“fr”、Source は “account”、“billing_address”、“default”)。client.UpdateAccount(ctx, glac.AccountLanguage("de")) で選び、glac.NoAccountLanguage() で選択を取り消すと、再び請求先住所で決まります。撤回の受領通知と購入の確認はこの言語で書かれ、それ以外の通知はすべて英語です。
アカウントの Keeps(AccountKeeps。コントロールプレーンの背後にある場合)は、キーのプロジェクトが保持するドライブとボリュームを、作成時に適用される数値(403 drive_limit_reached、volume_limit_reached)で、それぞれプロジェクトが持っている量とともに示します。Volumes(KeepsCount:Limit、Used、“plan” か “operator” の Source)、VolumeBytes(KeepsSize:1 つの最大サイズと、その Source)、VolumesBytes(KeepsTotal:全体の合計サイズの上限。上限なしなら Limit は nil。そして Used)、そしてサイズを指定せずに作った場合のサイズ UnsizedBytes です。アカウント独自の数値(“operator”)は、client.RequestLimit(ctx, "volumes", …) か "volume_bytes" で申請します。
**すぐに受け取る購入(StartNow)。**欧州経済領域または英国の消費者(確認済み、または確認中の税番号を持たないアカウント)は、購入から 14 日以内であれば撤回でき、購入したものがすぐに提供されるのは、本人が明示的に求めた場合だけです。glac.StartNow() がその要求を伝えます。client.TopUp(ctx, 20, glac.StartNow())、client.UpdateBilling(ctx, glac.Plan("paid"), glac.StartNow())(無料プランから購入する有料プラン)、client.UpdateBalance(ctx, glac.AutoReload(true), glac.StartNow())(自動チャージがオンの間のすべての自動チャージ)で、コンソールのチェックボックスの横に表示される文言(GET /v1/billing/withdrawals の right.start_now にもあるもの)で伝えます。
撤回できる 14 日間のうちに、この購入をすぐに提供するよう求めます。撤回した場合は、それまでに提供された分を支払います。チャージのクレジットをすべて使った時点で全額が提供されたことになり、それ以降は撤回できなくなることを理解しています。
サービスはすぐに始まります。14 日以内なら購入者はまだ撤回でき、その場合はそれまでに提供された分を支払います。すべてが提供されると(チャージのクレジットをすべて使うと)、撤回する権利はなくなります。この要求は、購入する本人が求めたときだけ指定してください。SDK は、指定されない限り決して送りません。指定がなければ、そのようなアカウントは拒否されます。Status が 400、Code が “start_now_required”、Param が “start_now” の *Error で、国名を挙げ、要求の文言を引用したメッセージが付き、何も購入されません。要求なしで自動チャージをオンにしたアカウントでは何もチャージされず、月に 1 回通知されます(イベント auto_reload.no_request。EventAutoReloadNoRequest で読みます。カードが登録されていないアカウントでは auto_reload.no_card と EventAutoReloadNoCard)。
エラー
0 以外の終了コードは結果です。res.ExitCode を読んでください。API のエラーは、Status、Type、Code、Param、Retryable、RequestID、Message、そしてエラーのページの該当するコードを指す DocsURL を持つ *glac.Error です。接続できない、タイムアウト、コンテキストの終了も *glac.Error で、Status は 0 です。errors.Is(err, context.DeadlineExceeded) もそのまま使えます。お金に関するエラー(402 account_in_debt、403 trust_limit_exceeded、409 no_card、400 start_now_required など)は、コントロールプレーン自身のメッセージを持ち、解除する方法を示します。
var e *glac.Error
if errors.As(err, &e) {
fmt.Println(e.Status, e.Code, e.RequestID)
}知っておくべき動作
- **スリープ中のサンドボックス。**サンドボックスがスリープ中や起動中であることを理由に失敗する呼び出しはありません。待ってから続行します。
res.Wokeとres.Wakeは、Runがサンドボックスを復帰させたかどうかと、その所要時間を示します。クライアントのOnResponse(f)は、すべての呼び出しについて同じものを受け取ります。 - **再試行。**応答がない場合や
retryableのエラーは、0.2 秒から倍々に間隔を空けて 2 回再試行されます(Retries(n))。すべてのPOSTにはIdempotency-Keyが付きます。IdempotencyKey(key)を使えば、再起動したプログラムが、以前に作ったサンドボックス、コマンド、バージョンを取り戻せます。 - **タイムアウト。**呼び出しは、コンテキストが終わるまで続きます。
RequestTimeout(指定しなければ 15 分)は API を待つ時間です。Timeout(d)はコマンドの制限時間で、過ぎるとコマンドは強制終了され、Statusはtimed_outになります。 - **期間と null。**期間と時刻は
time.Durationとtime.Timeです。API のnullに意味がある場合はそのためのオプションがあり(NeverSleep()、NoName()、NoEgress()、NoSleepNotice()、DefaultSleepHoldMax())、指定しなかったオプションは何も変えません。 - goroutine。
Client(とその製品のサービス)、Sandbox、Command、Filesは、複数の goroutine から使えます。