The k7-sdk PyPI package (import k7_sdk) wraps the K7 HTTP API in two clients. The legacy katakate name still installs but emits a deprecation warning.
Client— synchronous, backed byrequests.AsyncClient—asyncio-native, backed byhttpx.
Install#
Run this on your laptop / client. A k7 node (fresh Ubuntu 24.04) does not ship python3-venv; python3 -m venv … fails until sudo apt install -y python3-venv python3-pip.
The async client raises RuntimeError at construction time if httpx isn’t installed.
Always pass verify_ssl as the cluster CA path on the default HTTPS install (./k7-ca.crt, or /etc/k7/tls/ca.crt on the node). k7 api status prints a ready-to-paste snippet that includes it.
Quickstart#
Discover the endpoint with k7 api endpoint and the key with k7 generate-api-key <name> --role user --tenant <tenant> (--role is required since 0.5.0; see Tenants and roles). Humans can use an OIDC token instead of a key: pass token_provider= a callable returning the bearer token (for example a reader for the token in ~/.config/k7/credentials.json after k7 login, a GitHub Actions ID token, or a projected ServiceAccount token). Exactly one of api_key / token_provider must be given. On the default install the API presents a certificate signed by the cluster CA (/etc/k7/tls/ca.crt on the node) — copy it to the client and pass its path as verify_ssl. Clusters installed with --api-hostname (Let’s Encrypt) work with the default verify_ssl=True. See the CLI guide for full details.
Client reference#
| Method | Returns | Notes |
|---|---|---|
Client(endpoint, api_key=None, verify_ssl=True, token_provider=None) | — | Exactly one of api_key (sent as X-API-Key) or token_provider (a Callable[[], str] called per request, sent as Authorization: Bearer). verify_ssl is True (system trust store) or a CA bundle path (cluster CA). verify_ssl=False raises ValueError on an https:// URL — there is no insecure mode; use http:// only against a --api-insecure-http development install. |
whoami() | dict | The caller’s identity: subject, role, tenant, namespaces, nodes (GET /api/v1/auth/whoami). |
create(config: dict) | SandboxProxy | config matches SandboxConfig. |
list(namespace=None) | list[dict] | Omit namespace to list all. |
delete(name, namespace="default") | dict | |
delete_all(namespace="default") | dict | Returns {message, results: [{name, success, error}]}. |
get_metrics(namespace=None) | list[dict] | Per-sandbox cpu_usage / memory_usage. |
install(nodes: list[str]) | dict | Remote node install through the k7-node-installer (admin, development mode, --api-remote-install). Returns the 202 body with the operation id. The pre-0.5.0 playbook-upload form is gone. |
install_status(operation) | dict | Per-node pending / running / succeeded / failed for an install operation. |
pause(name, snapshot=None, namespace=...) | dict | Scale to 0; optional VolumeSnapshot name |
resume(name, namespace=...) | dict | Scale back to 1 |
fork(source, new_name, namespace=..., snapshot=None) | SandboxProxy | kql: disk clone + cold boot; k7d / k7d-fc: warm CoW fork (memory + disk) |
restore(snapshot, new_name, overrides=None, keep_snapshot=True) | SandboxProxy | New sandbox from a snapshot |
list_snapshots(...) / get_snapshot(...) / create_snapshot(...) / delete_snapshot(...) / gc_snapshots(...) | varies | Snapshot lifecycle (see Snapshots API) |
exec(name, command, namespace="default") | dict | Run a command without a proxy |
logs(name, tail=200, container="sandbox", since=0, namespace=...) | str | Snapshot of the pod logs |
nodes_storage() | dict | Per-node kfd thin-pool + k7d disk-pool utilization (see Nodes API). operator / admin only (403 for tenant roles). |
usage(start, end, tenant=None, group_by=None) | dict | Showback over [start, end] (unix seconds) from the cluster’s Prometheus; group_by is a comma list of tenant,namespace,backend,state. Tenant roles see their own tenant only. See Observability and metering. |
create_api_key(name, *, role, expires_days, tenant=None, namespaces=None, nodes=None) | dict | admin: mint a key; the response carries the one-time token. |
list_api_keys() / revoke_api_key(name) | list[dict] / dict | Key inventory (hashes never returned) and revocation. |
dedicate_node(node, tenant) / undedicate_node(node) | dict | Reserve a node for one tenant / release it (admin). |
get_role_bindings() / put_role_bindings(bindings, deny_subjects) | dict | Read / replace the OIDC role bindings ConfigMap (admin). |
SandboxProxy (returned by create) exposes:
exec(command: str) -> dict—{exit_code, stdout, stderr, duration_ms}delete() -> dict— shorthand forclient.delete(name, namespace)pause/resume/fork— same as the client methods, scoped to this sandboxsnapshot(name)— named VolumeSnapshot without pausinglogs(tail=200, container="sandbox", since=0)— log snapshot
The proxy keeps a reference to the Client, so calling sb.exec(...) after the parent client closes will raise.
All sandbox config fields#
The create() payload accepts every field from the API schema. Common ones:
See Sandboxes API for the full table.
env_file points to a path on the API node, not the client. To inject runtime env vars from the client, build them into your before_script (echo "KEY=value" > /etc/sandbox.env) or commit them to your sandbox image.
Wait until ready#
HTTP POST /sandboxes (and Client.create / k7 create) returns once Kubernetes objects exist — often while ready is still False. Poll list() before exec or curling a NodePort:
Pause, resume, fork#
pause, resume, and fork work on Client and on the SandboxProxy from create. Behavior depends on the backend:
kata-qemu-longhorn— fork clones the root disk via LonghornVolumeSnapshot(the fork cold-boots, ~45 s); pause/resume scale the Deployment and the PVC survives. Adocker: Truesandbox’s graph PVC is cloned too.k7d/k7d-fc— fork is a warm CoW copy of the whole VM (memory + disk + processes — including a livedocker: Trueengine, ~5 ms at the VMM, ~2 s end-to-end to a Ready pod); pause/resume freeze and thaw the live VM in place. Works for sandboxes on any node — the API forwards to the per-nodek7-agentwhen needed.
Forks inherit the source’s egress and ingress policy, but not its expose_ports Service.
See Snapshots & fork for timing notes and CLI equivalents.
Snapshots and restore#
Full HTTP detail: Snapshots API.
Async client#
AsyncClient mirrors the sync client surface (create, list, delete, delete_all, exec, get_metrics, aclose). Note that AsyncClient.exec is a top-level method (await k7.exec(name, command)) rather than a proxy method.
Concurrent sandbox fan-out#
Errors#
requests.HTTPError / httpx.HTTPStatusError are raised on non-2xx responses. The error body follows the API envelope:
Recover the structured error:
Tips#
- Always pass
namespace=if you use anything other thandefault. A tenant key (k7 generate-api-key NAME --role user --tenant team-a, optionally narrowed with-n) cannot list all namespaces or touch a namespace outside its tenant (403); onlyoperator/adminkeys see the whole cluster. - Rotate API keys with
k7 revoke-api-key <name>andk7 generate-api-key <name>. - The same operations are available via CLI (
k7 pause,k7 fork,k7 snapshot,k7 restore) — default CLI path is the HTTP API; use--coreonly on the cluster node.
