drukbox-python-sdk 0.3.0__py3-none-any.whl → 0.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {drukbox_python_sdk-0.3.0.dist-info → drukbox_python_sdk-0.5.0.dist-info}/METADATA +3 -1
- drukbox_python_sdk-0.5.0.dist-info/RECORD +7 -0
- {drukbox_python_sdk-0.3.0.dist-info → drukbox_python_sdk-0.5.0.dist-info}/WHEEL +1 -1
- drukbox_sdk/__init__.py +2 -0
- drukbox_sdk/api.py +19 -10
- drukbox_sdk/exceptions.py +12 -0
- drukbox_python_sdk-0.3.0.dist-info/RECORD +0 -7
- {drukbox_python_sdk-0.3.0.dist-info → drukbox_python_sdk-0.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: drukbox-python-sdk
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.0
|
|
4
4
|
Summary: Async Python client for Drukbox.
|
|
5
5
|
Project-URL: Homepage, https://github.com/clawhaven/drukbox-python-sdk
|
|
6
6
|
Project-URL: Repository, https://github.com/clawhaven/drukbox-python-sdk
|
|
@@ -59,6 +59,8 @@ finally:
|
|
|
59
59
|
few minutes worst case. The SDK's default `timeout` (300s) covers this. Pass
|
|
60
60
|
an `idempotency_key` for retry safety: a retry with the same key after a
|
|
61
61
|
successful provision returns the original host instead of creating a duplicate.
|
|
62
|
+
A provider at its host limit raises `SandboxCapacityError`, a
|
|
63
|
+
`SandboxUnavailableError` whose `retry_after` gives the seconds to wait.
|
|
62
64
|
|
|
63
65
|
`SandboxAPI.from_env(prefix="SANDBOX_")` reads
|
|
64
66
|
`SANDBOX_SERVICE_URL`, `SANDBOX_SERVICE_TOKEN`, and optional
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
drukbox_sdk/__init__.py,sha256=OgssAANGnl49_1N_EKMXSDlgWfedO9jUAnLVxgkJY2Q,1066
|
|
2
|
+
drukbox_sdk/api.py,sha256=z-Sjh_rdqIFpMgzfG7_RktxbH6wS8rToHfy0B8FNZkI,24668
|
|
3
|
+
drukbox_sdk/exceptions.py,sha256=0CKbb0Ec4RSWPB8t31WJgO1yQQ10BwTPqoqS1_EieB4,2599
|
|
4
|
+
drukbox_python_sdk-0.5.0.dist-info/METADATA,sha256=mrbJKSw-RuyIXSPaxtKn6DDYqP9Y7IBlw0NvLetTL-0,6734
|
|
5
|
+
drukbox_python_sdk-0.5.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
6
|
+
drukbox_python_sdk-0.5.0.dist-info/licenses/LICENSE,sha256=zM66rWL3BWGJBa_mZPnM0WUomSSZ1xtWVtGQovQ71M8,1078
|
|
7
|
+
drukbox_python_sdk-0.5.0.dist-info/RECORD,,
|
drukbox_sdk/__init__.py
CHANGED
|
@@ -19,6 +19,7 @@ from .api import (
|
|
|
19
19
|
from .exceptions import (
|
|
20
20
|
SandboxAPIError,
|
|
21
21
|
SandboxAuthError,
|
|
22
|
+
SandboxCapacityError,
|
|
22
23
|
SandboxConflictError,
|
|
23
24
|
SandboxNotFoundError,
|
|
24
25
|
SandboxProvisioningError,
|
|
@@ -36,6 +37,7 @@ __all__ = [
|
|
|
36
37
|
"SandboxAPI",
|
|
37
38
|
"SandboxAPIError",
|
|
38
39
|
"SandboxAuthError",
|
|
40
|
+
"SandboxCapacityError",
|
|
39
41
|
"SandboxConflictError",
|
|
40
42
|
"SandboxHost",
|
|
41
43
|
"SandboxNotFoundError",
|
drukbox_sdk/api.py
CHANGED
|
@@ -47,6 +47,7 @@ import httpx
|
|
|
47
47
|
|
|
48
48
|
from .exceptions import (
|
|
49
49
|
SandboxAuthError,
|
|
50
|
+
SandboxCapacityError,
|
|
50
51
|
SandboxConflictError,
|
|
51
52
|
SandboxNotFoundError,
|
|
52
53
|
SandboxProvisioningError,
|
|
@@ -197,7 +198,8 @@ class DoctorReport:
|
|
|
197
198
|
|
|
198
199
|
ok: bool
|
|
199
200
|
active_provider: str
|
|
200
|
-
|
|
201
|
+
# Whether the active provider's hosts join the tailnet.
|
|
202
|
+
tailnet: bool
|
|
201
203
|
checks: list[DoctorCheck]
|
|
202
204
|
|
|
203
205
|
|
|
@@ -435,14 +437,15 @@ class SandboxAPI:
|
|
|
435
437
|
base_image: str | None = None,
|
|
436
438
|
label: str | None = None,
|
|
437
439
|
) -> SandboxTemplate:
|
|
438
|
-
"""Start a template build
|
|
439
|
-
|
|
440
|
-
The service responds 202 with
|
|
441
|
-
:meth:`get_template` until the status
|
|
442
|
-
``"failed"``. A failed record carries the
|
|
443
|
-
``last_error``. A repeated post with the same provider,
|
|
444
|
-
image, and setup script returns the existing record
|
|
445
|
-
|
|
440
|
+
"""Start a template build.
|
|
441
|
+
|
|
442
|
+
The service pulls the base image, then responds 202 with
|
|
443
|
+
``status="building"``. Poll :meth:`get_template` until the status
|
|
444
|
+
becomes ``"available"`` or ``"failed"``. A failed record carries the
|
|
445
|
+
reason in ``last_error``. A repeated post with the same provider,
|
|
446
|
+
base image digest, and setup script returns the existing record. A
|
|
447
|
+
``"failed"`` record builds again and keeps its ``last_error`` until
|
|
448
|
+
that build ends.
|
|
446
449
|
"""
|
|
447
450
|
|
|
448
451
|
payload: dict[str, Any] = {"setup_script": setup_script}
|
|
@@ -488,7 +491,8 @@ class SandboxAPI:
|
|
|
488
491
|
return DoctorReport(
|
|
489
492
|
ok=data["ok"],
|
|
490
493
|
active_provider=data["active_provider"],
|
|
491
|
-
|
|
494
|
+
# drukbox before "Join the tailnet per provider" sent tailscale_enabled.
|
|
495
|
+
tailnet=data["tailnet"] if "tailnet" in data else data["tailscale_enabled"],
|
|
492
496
|
checks=[DoctorCheck(**check) for check in data["checks"]],
|
|
493
497
|
)
|
|
494
498
|
|
|
@@ -614,6 +618,11 @@ class SandboxAPI:
|
|
|
614
618
|
raise SandboxProvisioningError(json_response.get("detail", "provisioning failed"))
|
|
615
619
|
|
|
616
620
|
if response.status_code == 503:
|
|
621
|
+
if json_response.get("error_code") == "CAPACITY":
|
|
622
|
+
raise SandboxCapacityError(
|
|
623
|
+
json_response.get("detail", "provider at host limit"),
|
|
624
|
+
retry_after=int(response.headers["Retry-After"]),
|
|
625
|
+
)
|
|
617
626
|
raise SandboxUnavailableError(json_response.get("detail", "service unavailable"))
|
|
618
627
|
|
|
619
628
|
if response.status_code == 422:
|
drukbox_sdk/exceptions.py
CHANGED
|
@@ -18,6 +18,18 @@ class SandboxUnavailableError(RuntimeError):
|
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
class SandboxCapacityError(SandboxUnavailableError):
|
|
22
|
+
"""503 — the provider is at its host limit.
|
|
23
|
+
|
|
24
|
+
``retry_after`` is the service's ``Retry-After`` value in seconds:
|
|
25
|
+
wait at least that long before the next create.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, message: str, retry_after: int) -> None:
|
|
29
|
+
super().__init__(message)
|
|
30
|
+
self.retry_after = retry_after
|
|
31
|
+
|
|
32
|
+
|
|
21
33
|
class SandboxAPIError(RuntimeError):
|
|
22
34
|
"""Base for any error the sandbox service returned via HTTP."""
|
|
23
35
|
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
drukbox_sdk/__init__.py,sha256=bU2rOTzC3GMXSpiXvoMVwFOuKJUPZWSXhnteaRFxT_Y,1012
|
|
2
|
-
drukbox_sdk/api.py,sha256=eoXXnK8mkrSK9Q4tRSuVbN-6mSjbBTTeEsH_jF3U_wY,24118
|
|
3
|
-
drukbox_sdk/exceptions.py,sha256=Vzs4zVOywWsWfiZm6vgQ65ScI3Nn7zLGVj-8eT1YAR0,2224
|
|
4
|
-
drukbox_python_sdk-0.3.0.dist-info/METADATA,sha256=KL-_BzJPSEVgimNohBs8BIxhwcU8dreFTdVSihBlUaI,6599
|
|
5
|
-
drukbox_python_sdk-0.3.0.dist-info/WHEEL,sha256=zOwg4jB6zX2kU910N-cMawjivD6tO8NEWvE12je1bVk,87
|
|
6
|
-
drukbox_python_sdk-0.3.0.dist-info/licenses/LICENSE,sha256=zM66rWL3BWGJBa_mZPnM0WUomSSZ1xtWVtGQovQ71M8,1078
|
|
7
|
-
drukbox_python_sdk-0.3.0.dist-info/RECORD,,
|
|
File without changes
|