boxd 0.1.0.dev2__tar.gz → 0.1.1__tar.gz

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.
Files changed (42) hide show
  1. {boxd-0.1.0.dev2/src/boxd.egg-info → boxd-0.1.1}/PKG-INFO +16 -5
  2. {boxd-0.1.0.dev2 → boxd-0.1.1}/README.md +14 -3
  3. {boxd-0.1.0.dev2 → boxd-0.1.1}/pyproject.toml +8 -2
  4. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/__init__.py +7 -1
  5. boxd-0.1.1/src/boxd/_generated/api_pb2.py +226 -0
  6. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/_generated/api_pb2_grpc.py +43 -0
  7. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/_sync.py +2 -0
  8. boxd-0.1.1/src/boxd/_version_check.py +169 -0
  9. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/client.py +34 -5
  10. {boxd-0.1.0.dev2 → boxd-0.1.1/src/boxd.egg-info}/PKG-INFO +16 -5
  11. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd.egg-info/SOURCES.txt +3 -1
  12. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd.egg-info/requires.txt +1 -1
  13. {boxd-0.1.0.dev2 → boxd-0.1.1}/tests/test_e2e.py +10 -0
  14. {boxd-0.1.0.dev2 → boxd-0.1.1}/tests/test_v2.py +4 -2
  15. boxd-0.1.1/tests/test_version_check.py +178 -0
  16. boxd-0.1.0.dev2/src/boxd/_generated/api_pb2.py +0 -222
  17. {boxd-0.1.0.dev2 → boxd-0.1.1}/LICENSE +0 -0
  18. {boxd-0.1.0.dev2 → boxd-0.1.1}/setup.cfg +0 -0
  19. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/_generated/__init__.py +0 -0
  20. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/_utils.py +0 -0
  21. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/aio.py +0 -0
  22. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/auth.py +0 -0
  23. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/box.py +0 -0
  24. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/boxes.py +0 -0
  25. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/disks.py +0 -0
  26. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/domains.py +0 -0
  27. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/errors.py +0 -0
  28. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/exec.py +0 -0
  29. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/networks.py +0 -0
  30. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/templates.py +0 -0
  31. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/tokens.py +0 -0
  32. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd/types.py +0 -0
  33. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd.egg-info/dependency_links.txt +0 -0
  34. {boxd-0.1.0.dev2 → boxd-0.1.1}/src/boxd.egg-info/top_level.txt +0 -0
  35. {boxd-0.1.0.dev2 → boxd-0.1.1}/tests/test_auth.py +0 -0
  36. {boxd-0.1.0.dev2 → boxd-0.1.1}/tests/test_boxes.py +0 -0
  37. {boxd-0.1.0.dev2 → boxd-0.1.1}/tests/test_e2e_v2.py +0 -0
  38. {boxd-0.1.0.dev2 → boxd-0.1.1}/tests/test_exec.py +0 -0
  39. {boxd-0.1.0.dev2 → boxd-0.1.1}/tests/test_files.py +0 -0
  40. {boxd-0.1.0.dev2 → boxd-0.1.1}/tests/test_lifecycle.py +0 -0
  41. {boxd-0.1.0.dev2 → boxd-0.1.1}/tests/test_proxies.py +0 -0
  42. {boxd-0.1.0.dev2 → boxd-0.1.1}/tests/test_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boxd
3
- Version: 0.1.0.dev2
3
+ Version: 0.1.1
4
4
  Summary: Python SDK for the boxd cloud VM platform
5
5
  Author: Azin
6
6
  License-Expression: MIT
@@ -22,7 +22,7 @@ Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
23
  Requires-Dist: grpcio>=1.60
24
24
  Requires-Dist: protobuf>=4.25
25
- Requires-Dist: httpx>=0.27
25
+ Requires-Dist: httpx<1,>=0.27
26
26
  Provides-Extra: dev
27
27
  Requires-Dist: grpcio-tools>=1.60; extra == "dev"
28
28
  Requires-Dist: pytest>=8; extra == "dev"
@@ -65,16 +65,27 @@ Compute() # reads BOXD_API_KEY or BOXD_TOKEN
65
65
 
66
66
  ## Configuration
67
67
 
68
- The SDK reads its endpoint configuration from constructor arguments or env vars:
68
+ Pick a named cluster preset:
69
+
70
+ ```python
71
+ Compute(api_key="bxk_...") # production (default)
72
+ Compute(api_key="bxd_...", environment="staging") # boxd-stg.sh
73
+ ```
74
+
75
+ `environment` also reads from the `BOXD_ENVIRONMENT` env var (`"production"` or `"staging"`).
76
+
77
+ For custom or self-hosted endpoints, override URLs explicitly — these take precedence over `environment`:
69
78
 
70
79
  ```python
71
80
  Compute(
72
81
  api_key="bxk_...",
73
- api_url="http://boxd.sh:9443", # default
74
- exchange_url="https://boxd.sh/api/v1/auth/token", # default
82
+ api_url="http://my-boxd.example.com:9443",
83
+ exchange_url="https://my-boxd.example.com/api/v1/auth/token",
75
84
  )
76
85
  ```
77
86
 
87
+ Env vars `BOXD_API_URL` / `BOXD_EXCHANGE_URL` override the preset too.
88
+
78
89
  Equivalent env vars: `BOXD_API_KEY`, `BOXD_TOKEN`, `BOXD_API_URL`, `BOXD_EXCHANGE_URL`.
79
90
 
80
91
  `api_url` accepts an optional URL scheme that controls TLS:
@@ -32,16 +32,27 @@ Compute() # reads BOXD_API_KEY or BOXD_TOKEN
32
32
 
33
33
  ## Configuration
34
34
 
35
- The SDK reads its endpoint configuration from constructor arguments or env vars:
35
+ Pick a named cluster preset:
36
+
37
+ ```python
38
+ Compute(api_key="bxk_...") # production (default)
39
+ Compute(api_key="bxd_...", environment="staging") # boxd-stg.sh
40
+ ```
41
+
42
+ `environment` also reads from the `BOXD_ENVIRONMENT` env var (`"production"` or `"staging"`).
43
+
44
+ For custom or self-hosted endpoints, override URLs explicitly — these take precedence over `environment`:
36
45
 
37
46
  ```python
38
47
  Compute(
39
48
  api_key="bxk_...",
40
- api_url="http://boxd.sh:9443", # default
41
- exchange_url="https://boxd.sh/api/v1/auth/token", # default
49
+ api_url="http://my-boxd.example.com:9443",
50
+ exchange_url="https://my-boxd.example.com/api/v1/auth/token",
42
51
  )
43
52
  ```
44
53
 
54
+ Env vars `BOXD_API_URL` / `BOXD_EXCHANGE_URL` override the preset too.
55
+
45
56
  Equivalent env vars: `BOXD_API_KEY`, `BOXD_TOKEN`, `BOXD_API_URL`, `BOXD_EXCHANGE_URL`.
46
57
 
47
58
  `api_url` accepts an optional URL scheme that controls TLS:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "boxd"
3
- version = "0.1.0.dev2"
3
+ version = "0.1.1"
4
4
  description = "Python SDK for the boxd cloud VM platform"
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -22,7 +22,13 @@ classifiers = [
22
22
  dependencies = [
23
23
  "grpcio>=1.60",
24
24
  "protobuf>=4.25",
25
- "httpx>=0.27",
25
+ # Cap below 1.0: httpx 1.0 (currently in pre-release as 1.0.devN)
26
+ # removed `httpx.AsyncClient`, which auth.py uses for the API-key →
27
+ # JWT exchange. Without this cap, anyone running `pip install --pre
28
+ # boxd` (necessary for staging dev builds) gets httpx 1.0.devN and
29
+ # the SDK crashes on the first call. Re-evaluate when httpx 1.0 ships
30
+ # stable and the AsyncClient migration path is documented.
31
+ "httpx>=0.27,<1",
26
32
  ]
27
33
 
28
34
  [project.urls]
@@ -63,7 +63,13 @@ from .errors import (
63
63
  ConnectionError,
64
64
  )
65
65
 
66
- __version__ = "0.1.0"
66
+ try:
67
+ from importlib.metadata import version as _pkg_version
68
+
69
+ __version__ = _pkg_version("boxd")
70
+ except Exception:
71
+ # Fallback for source checkouts where the package isn't installed.
72
+ __version__ = "0.0.0+source"
67
73
 
68
74
  __all__ = [
69
75
  # Main client (sync)
@@ -0,0 +1,226 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Generated by the protocol buffer compiler. DO NOT EDIT!
3
+ # NO CHECKED-IN PROTOBUF GENCODE
4
+ # source: api.proto
5
+ # Protobuf Python Version: 6.31.1
6
+ """Generated protocol buffer code."""
7
+ from google.protobuf import descriptor as _descriptor
8
+ from google.protobuf import descriptor_pool as _descriptor_pool
9
+ from google.protobuf import runtime_version as _runtime_version
10
+ from google.protobuf import symbol_database as _symbol_database
11
+ from google.protobuf.internal import builder as _builder
12
+ _runtime_version.ValidateProtobufRuntimeVersion(
13
+ _runtime_version.Domain.PUBLIC,
14
+ 6,
15
+ 31,
16
+ 1,
17
+ '',
18
+ 'api.proto'
19
+ )
20
+ # @@protoc_insertion_point(imports)
21
+
22
+ _sym_db = _symbol_database.Default()
23
+
24
+
25
+
26
+
27
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\tapi.proto\x12\x0b\x62oxd.api.v1\"\xbf\x01\n\x08VmConfig\x12\x0c\n\x04vcpu\x18\x01 \x01(\r\x12\x14\n\x0cmemory_bytes\x18\x02 \x01(\x04\x12\x12\n\ndisk_bytes\x18\x03 \x01(\x04\x12#\n\x03srf\x18\x04 \x01(\x0b\x32\x16.boxd.api.v1.SrfConfig\x12+\n\x07network\x18\x05 \x01(\x0b\x32\x1a.boxd.api.v1.NetworkConfig\x12)\n\x07volumes\x18\x06 \x03(\x0b\x32\x18.boxd.api.v1.VolumeMount\"t\n\tSrfConfig\x12&\n\x19\x61uto_suspend_timeout_secs\x18\x01 \x01(\rH\x00\x88\x01\x01\x12!\n\x19\x61uto_destroy_timeout_secs\x18\x02 \x01(\rB\x1c\n\x1a_auto_suspend_timeout_secs\"F\n\rNetworkConfig\x12\x0b\n\x03ssh\x18\x01 \x01(\x08\x12(\n\x07proxies\x18\x02 \x03(\x0b\x32\x17.boxd.api.v1.ProxyEntry\"(\n\nProxyEntry\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0c\n\x04port\x18\x02 \x01(\r\"E\n\x0bVolumeMount\x12\x0f\n\x07\x64isk_id\x18\x01 \x01(\t\x12\x12\n\nmount_path\x18\x02 \x01(\t\x12\x11\n\tread_only\x18\x03 \x01(\x08\"\xac\x01\n\x0f\x43reateVmRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\timage_ref\x18\x02 \x01(\t\x12 \n\x03\x65nv\x18\x05 \x03(\x0b\x32\x13.boxd.api.v1.EnvVar\x12\x0b\n\x03\x63md\x18\x06 \x03(\t\x12\x16\n\x0erestart_policy\x18\x07 \x01(\t\x12%\n\x06\x63onfig\x18\x08 \x01(\x0b\x32\x15.boxd.api.v1.VmConfigJ\x04\x08\x03\x10\x04J\x04\x08\x04\x10\x05\"$\n\x06\x45nvVar\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\r\n\x05value\x18\x02 \x01(\t\"\x84\x01\n\x10\x43reateVmResponse\x12\r\n\x05vm_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\tpublic_ip\x18\x03 \x01(\t\x12\x0b\n\x03url\x18\x04 \x01(\t\x12\r\n\x05image\x18\x05 \x01(\t\x12\x0e\n\x06status\x18\x06 \x01(\t\x12\x14\n\x0c\x62oot_time_ms\x18\x07 \x01(\x04\"!\n\x10\x44\x65stroyVmRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\"\x13\n\x11\x44\x65stroyVmResponse\"\x1f\n\x0eStartVmRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\"\x11\n\x0fStartVmResponse\"\x1e\n\rStopVmRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\"\x10\n\x0eStopVmResponse\" \n\x0fRebootVmRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\"\x12\n\x10RebootVmResponse\"!\n\x10SuspendVmRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\"\'\n\x11SuspendVmResponse\x12\x12\n\nsuspend_us\x18\x01 \x01(\x04\" \n\x0fResumeVmRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\"%\n\x10ResumeVmResponse\x12\x11\n\tresume_us\x18\x01 \x01(\x04\"\x1d\n\x0cGetVmRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\"\xb1\x01\n\rGetVmResponse\x12\r\n\x05vm_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\timage_ref\x18\x03 \x01(\t\x12\x11\n\tpublic_ip\x18\x04 \x01(\t\x12\x0e\n\x06status\x18\x05 \x01(\t\x12\x16\n\x0erestart_policy\x18\x06 \x01(\t\x12\x12\n\ndisk_bytes\x18\x07 \x01(\x04\x12!\n\x19\x61uto_suspend_timeout_secs\x18\x08 \x01(\r\"\x10\n\x0eListVmsRequest\":\n\x0fListVmsResponse\x12\'\n\x03vms\x18\x01 \x03(\x0b\x32\x1a.boxd.api.v1.GetVmResponse\"2\n\x11StreamLogsRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\x12\x0e\n\x06\x66ollow\x18\x02 \x01(\x08\"\x18\n\x08LogChunk\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\"h\n\tExecChunk\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\x12\r\n\x05stdin\x18\x02 \x01(\x08\x12\x0b\n\x03tty\x18\x03 \x01(\x08\x12\x0f\n\x07\x63ommand\x18\x04 \x01(\t\x12\r\n\x05vm_id\x18\x05 \x01(\t\x12\x11\n\texit_code\x18\x06 \x01(\x05\"$\n\x14\x43reateNetworkRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\"+\n\x15\x43reateNetworkResponse\x12\x12\n\nnetwork_id\x18\x01 \x01(\t\"\x15\n\x13ListNetworksRequest\"B\n\x14ListNetworksResponse\x12*\n\x08networks\x18\x01 \x03(\x0b\x32\x18.boxd.api.v1.NetworkInfo\"A\n\x0bNetworkInfo\x12\x12\n\nnetwork_id\x18\x01 \x01(\t\x12\x0e\n\x06subnet\x18\x02 \x01(\t\x12\x0e\n\x06status\x18\x03 \x01(\t\"2\n\x11\x42indDomainRequest\x12\x0e\n\x06\x64omain\x18\x01 \x01(\t\x12\r\n\x05vm_id\x18\x02 \x01(\t\"\x14\n\x12\x42indDomainResponse\"%\n\x13UnbindDomainRequest\x12\x0e\n\x06\x64omain\x18\x01 \x01(\t\"\x16\n\x14UnbindDomainResponse\"\x14\n\x12ListDomainsRequest\"?\n\x13ListDomainsResponse\x12(\n\x07\x64omains\x18\x01 \x03(\x0b\x32\x17.boxd.api.v1.DomainInfo\"+\n\nDomainInfo\x12\x0e\n\x06\x64omain\x18\x01 \x01(\t\x12\r\n\x05vm_id\x18\x02 \x01(\t\"\x12\n\x10GetConfigRequest\"8\n\x11GetConfigResponse\x12\x15\n\rdefault_image\x18\x01 \x01(\t\x12\x0c\n\x04zone\x18\x02 \x01(\t\"\x0f\n\rWhoamiRequest\"Z\n\x0eWhoamiResponse\x12\x0f\n\x07user_id\x18\x01 \x01(\t\x12\x1b\n\x13pubkey_fingerprints\x18\x02 \x03(\t\x12\x1a\n\x12\x64\x65\x66\x61ult_network_id\x18\x03 \x01(\t\"-\n\x12\x43reateTokenRequest\x12\x17\n\x0f\x65xpires_in_secs\x18\x01 \x01(\x04\"8\n\x13\x43reateTokenResponse\x12\r\n\x05token\x18\x01 \x01(\t\x12\x12\n\nexpires_at\x18\x02 \x01(\x03\"\x13\n\x11ListTokensRequest\"<\n\x12ListTokensResponse\x12&\n\x06tokens\x18\x01 \x03(\x0b\x32\x16.boxd.api.v1.TokenInfo\"@\n\tTokenInfo\x12\x0b\n\x03jti\x18\x01 \x01(\t\x12\x12\n\ncreated_at\x18\x02 \x01(\x03\x12\x12\n\nexpires_at\x18\x03 \x01(\x03\"!\n\x12RevokeTokenRequest\x12\x0b\n\x03jti\x18\x01 \x01(\t\"\x15\n\x13RevokeTokenResponse\"Z\n\rForkVmRequest\x12\x14\n\x0csource_vm_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12%\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x15.boxd.api.v1.VmConfig\"\x97\x01\n\x0e\x46orkVmResponse\x12\r\n\x05vm_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\tpublic_ip\x18\x03 \x01(\t\x12\x0b\n\x03url\x18\x04 \x01(\t\x12\r\n\x05image\x18\x05 \x01(\t\x12\x0e\n\x06status\x18\x06 \x01(\t\x12\x13\n\x0b\x66orked_from\x18\x07 \x01(\t\x12\x14\n\x0c\x62oot_time_ms\x18\x08 \x01(\x04\"%\n\x12ListProxiesRequest\x12\x0f\n\x07vm_name\x18\x01 \x01(\t\">\n\x13ListProxiesResponse\x12\'\n\x07proxies\x18\x01 \x03(\x0b\x32\x16.boxd.api.v1.ProxyInfo\"r\n\tProxyInfo\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07vm_name\x18\x02 \x01(\t\x12\x0e\n\x06\x64omain\x18\x03 \x01(\t\x12\x0c\n\x04port\x18\x04 \x01(\r\x12\x12\n\nis_default\x18\x05 \x01(\x08\x12\x14\n\x0cport_display\x18\x06 \x01(\t\"A\n\x12\x43reateProxyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07vm_name\x18\x02 \x01(\t\x12\x0c\n\x04port\x18\x03 \x01(\r\"R\n\x13\x43reateProxyResponse\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07vm_name\x18\x02 \x01(\t\x12\x0e\n\x06\x64omain\x18\x03 \x01(\t\x12\x0c\n\x04port\x18\x04 \x01(\r\"3\n\x12\x44\x65leteProxyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07vm_name\x18\x02 \x01(\t\"\x15\n\x13\x44\x65leteProxyResponse\"B\n\x13SetProxyPortRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x0f\n\x07vm_name\x18\x02 \x01(\t\x12\x0c\n\x04port\x18\x03 \x01(\t\"\x16\n\x14SetProxyPortResponse\">\n\x11UploadFileRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\"\x14\n\x12UploadFileResponse\"2\n\x13\x44ownloadFileRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\x12\x0c\n\x04path\x18\x02 \x01(\t\"$\n\x14\x44ownloadFileResponse\x12\x0c\n\x04\x64\x61ta\x18\x01 \x01(\x0c\"_\n\x15\x43reateTemplateRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x11\n\timage_ref\x18\x02 \x01(\t\x12%\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x15.boxd.api.v1.VmConfig\"K\n\x16\x43reateTemplateResponse\x12\x13\n\x0btemplate_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06status\x18\x03 \x01(\t\"\x16\n\x14ListTemplatesRequest\"E\n\x15ListTemplatesResponse\x12,\n\ttemplates\x18\x01 \x03(\x0b\x32\x19.boxd.api.v1.TemplateInfo\"x\n\x0cTemplateInfo\x12\x13\n\x0btemplate_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\timage_ref\x18\x03 \x01(\t\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x0c\n\x04vcpu\x18\x05 \x01(\r\x12\x14\n\x0cmemory_bytes\x18\x06 \x01(\x04\",\n\x15\x44\x65leteTemplateRequest\x12\x13\n\x0btemplate_id\x18\x01 \x01(\t\"\x18\n\x16\x44\x65leteTemplateResponse\"g\n\x1b\x43reateVmFromTemplateRequest\x12\x13\n\x0btemplate_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12%\n\x06\x63onfig\x18\x03 \x01(\x0b\x32\x15.boxd.api.v1.VmConfig\"\x81\x01\n\x1c\x43reateVmFromTemplateResponse\x12\r\n\x05vm_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x11\n\tpublic_ip\x18\x03 \x01(\t\x12\x0b\n\x03url\x18\x04 \x01(\t\x12\x0e\n\x06status\x18\x05 \x01(\t\x12\x14\n\x0c\x62oot_time_ms\x18\x06 \x01(\x04\"5\n\x11\x43reateDiskRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x12\n\nsize_bytes\x18\x02 \x01(\x04\"W\n\x12\x43reateDiskResponse\x12\x0f\n\x07\x64isk_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\nsize_bytes\x18\x03 \x01(\x04\x12\x0e\n\x06status\x18\x04 \x01(\t\"\x12\n\x10ListDisksRequest\"9\n\x11ListDisksResponse\x12$\n\x05\x64isks\x18\x01 \x03(\x0b\x32\x15.boxd.api.v1.DiskInfo\"\x92\x01\n\x08\x44iskInfo\x12\x0f\n\x07\x64isk_id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\nsize_bytes\x18\x03 \x01(\x04\x12\x0e\n\x06status\x18\x04 \x01(\t\x12\x11\n\tworker_id\x18\x05 \x01(\t\x12\x30\n\x0b\x61ttachments\x18\x06 \x03(\x0b\x32\x1b.boxd.api.v1.DiskAttachment\"X\n\x0e\x44iskAttachment\x12\r\n\x05vm_id\x18\x01 \x01(\t\x12\x0f\n\x07vm_name\x18\x02 \x01(\t\x12\x12\n\nmount_path\x18\x03 \x01(\t\x12\x12\n\nmount_mode\x18\x04 \x01(\t\"Z\n\x11\x41ttachDiskRequest\x12\x0f\n\x07\x64isk_id\x18\x01 \x01(\t\x12\r\n\x05vm_id\x18\x02 \x01(\t\x12\x12\n\nmount_path\x18\x03 \x01(\t\x12\x11\n\tread_only\x18\x04 \x01(\x08\"\x14\n\x12\x41ttachDiskResponse\"3\n\x11\x44\x65tachDiskRequest\x12\x0f\n\x07\x64isk_id\x18\x01 \x01(\t\x12\r\n\x05vm_id\x18\x02 \x01(\t\"\x14\n\x12\x44\x65tachDiskResponse\"%\n\x12\x44\x65stroyDiskRequest\x12\x0f\n\x07\x64isk_id\x18\x01 \x01(\t\"\x15\n\x13\x44\x65stroyDiskResponse\"C\n\x1cSetAutoSuspendTimeoutRequest\x12\r\n\x05vm_id\x18\x01 \x01(\t\x12\x14\n\x0ctimeout_secs\x18\x02 \x01(\r\"\x1f\n\x1dSetAutoSuspendTimeoutResponse\"<\n\x13\x43reateApiKeyRequest\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x17\n\x0f\x65xpires_in_secs\x18\x02 \x01(\x04\"G\n\x14\x43reateApiKeyResponse\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0f\n\x07\x61pi_key\x18\x02 \x01(\t\x12\x12\n\nexpires_at\x18\x03 \x01(\x03\"\x14\n\x12ListApiKeysRequest\"<\n\x13ListApiKeysResponse\x12%\n\x04keys\x18\x01 \x03(\x0b\x32\x17.boxd.api.v1.ApiKeyInfo\"x\n\nApiKeyInfo\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x12\n\nkey_prefix\x18\x03 \x01(\t\x12\x12\n\ncreated_at\x18\x04 \x01(\x03\x12\x14\n\x0clast_used_at\x18\x05 \x01(\x03\x12\x12\n\nexpires_at\x18\x06 \x01(\x03\"!\n\x13\x44\x65leteApiKeyRequest\x12\n\n\x02id\x18\x01 \x01(\t\"\x16\n\x14\x44\x65leteApiKeyResponse2\xd7\x19\n\x07\x42oxdApi\x12G\n\x08\x43reateVm\x12\x1c.boxd.api.v1.CreateVmRequest\x1a\x1d.boxd.api.v1.CreateVmResponse\x12J\n\tDestroyVm\x12\x1d.boxd.api.v1.DestroyVmRequest\x1a\x1e.boxd.api.v1.DestroyVmResponse\x12\x44\n\x07StartVm\x12\x1b.boxd.api.v1.StartVmRequest\x1a\x1c.boxd.api.v1.StartVmResponse\x12\x41\n\x06StopVm\x12\x1a.boxd.api.v1.StopVmRequest\x1a\x1b.boxd.api.v1.StopVmResponse\x12G\n\x08RebootVm\x12\x1c.boxd.api.v1.RebootVmRequest\x1a\x1d.boxd.api.v1.RebootVmResponse\x12>\n\x05GetVm\x12\x19.boxd.api.v1.GetVmRequest\x1a\x1a.boxd.api.v1.GetVmResponse\x12\x44\n\x07ListVms\x12\x1b.boxd.api.v1.ListVmsRequest\x1a\x1c.boxd.api.v1.ListVmsResponse\x12\x45\n\nStreamLogs\x12\x1e.boxd.api.v1.StreamLogsRequest\x1a\x15.boxd.api.v1.LogChunk0\x01\x12:\n\x04\x45xec\x12\x16.boxd.api.v1.ExecChunk\x1a\x16.boxd.api.v1.ExecChunk(\x01\x30\x01\x12V\n\rCreateNetwork\x12!.boxd.api.v1.CreateNetworkRequest\x1a\".boxd.api.v1.CreateNetworkResponse\x12S\n\x0cListNetworks\x12 .boxd.api.v1.ListNetworksRequest\x1a!.boxd.api.v1.ListNetworksResponse\x12M\n\nBindDomain\x12\x1e.boxd.api.v1.BindDomainRequest\x1a\x1f.boxd.api.v1.BindDomainResponse\x12S\n\x0cUnbindDomain\x12 .boxd.api.v1.UnbindDomainRequest\x1a!.boxd.api.v1.UnbindDomainResponse\x12P\n\x0bListDomains\x12\x1f.boxd.api.v1.ListDomainsRequest\x1a .boxd.api.v1.ListDomainsResponse\x12\x41\n\x06Whoami\x12\x1a.boxd.api.v1.WhoamiRequest\x1a\x1b.boxd.api.v1.WhoamiResponse\x12P\n\x0b\x43reateToken\x12\x1f.boxd.api.v1.CreateTokenRequest\x1a .boxd.api.v1.CreateTokenResponse\x12M\n\nListTokens\x12\x1e.boxd.api.v1.ListTokensRequest\x1a\x1f.boxd.api.v1.ListTokensResponse\x12P\n\x0bRevokeToken\x12\x1f.boxd.api.v1.RevokeTokenRequest\x1a .boxd.api.v1.RevokeTokenResponse\x12J\n\tGetConfig\x12\x1d.boxd.api.v1.GetConfigRequest\x1a\x1e.boxd.api.v1.GetConfigResponse\x12\x41\n\x06\x46orkVm\x12\x1a.boxd.api.v1.ForkVmRequest\x1a\x1b.boxd.api.v1.ForkVmResponse\x12P\n\x0bListProxies\x12\x1f.boxd.api.v1.ListProxiesRequest\x1a .boxd.api.v1.ListProxiesResponse\x12P\n\x0b\x43reateProxy\x12\x1f.boxd.api.v1.CreateProxyRequest\x1a .boxd.api.v1.CreateProxyResponse\x12P\n\x0b\x44\x65leteProxy\x12\x1f.boxd.api.v1.DeleteProxyRequest\x1a .boxd.api.v1.DeleteProxyResponse\x12S\n\x0cSetProxyPort\x12 .boxd.api.v1.SetProxyPortRequest\x1a!.boxd.api.v1.SetProxyPortResponse\x12M\n\nUploadFile\x12\x1e.boxd.api.v1.UploadFileRequest\x1a\x1f.boxd.api.v1.UploadFileResponse\x12S\n\x0c\x44ownloadFile\x12 .boxd.api.v1.DownloadFileRequest\x1a!.boxd.api.v1.DownloadFileResponse\x12J\n\tSuspendVm\x12\x1d.boxd.api.v1.SuspendVmRequest\x1a\x1e.boxd.api.v1.SuspendVmResponse\x12G\n\x08ResumeVm\x12\x1c.boxd.api.v1.ResumeVmRequest\x1a\x1d.boxd.api.v1.ResumeVmResponse\x12Y\n\x0e\x43reateTemplate\x12\".boxd.api.v1.CreateTemplateRequest\x1a#.boxd.api.v1.CreateTemplateResponse\x12V\n\rListTemplates\x12!.boxd.api.v1.ListTemplatesRequest\x1a\".boxd.api.v1.ListTemplatesResponse\x12Y\n\x0e\x44\x65leteTemplate\x12\".boxd.api.v1.DeleteTemplateRequest\x1a#.boxd.api.v1.DeleteTemplateResponse\x12k\n\x14\x43reateVmFromTemplate\x12(.boxd.api.v1.CreateVmFromTemplateRequest\x1a).boxd.api.v1.CreateVmFromTemplateResponse\x12n\n\x15SetAutoSuspendTimeout\x12).boxd.api.v1.SetAutoSuspendTimeoutRequest\x1a*.boxd.api.v1.SetAutoSuspendTimeoutResponse\x12M\n\nCreateDisk\x12\x1e.boxd.api.v1.CreateDiskRequest\x1a\x1f.boxd.api.v1.CreateDiskResponse\x12J\n\tListDisks\x12\x1d.boxd.api.v1.ListDisksRequest\x1a\x1e.boxd.api.v1.ListDisksResponse\x12M\n\nAttachDisk\x12\x1e.boxd.api.v1.AttachDiskRequest\x1a\x1f.boxd.api.v1.AttachDiskResponse\x12M\n\nDetachDisk\x12\x1e.boxd.api.v1.DetachDiskRequest\x1a\x1f.boxd.api.v1.DetachDiskResponse\x12P\n\x0b\x44\x65stroyDisk\x12\x1f.boxd.api.v1.DestroyDiskRequest\x1a .boxd.api.v1.DestroyDiskResponse\x12S\n\x0c\x43reateApiKey\x12 .boxd.api.v1.CreateApiKeyRequest\x1a!.boxd.api.v1.CreateApiKeyResponse\x12P\n\x0bListApiKeys\x12\x1f.boxd.api.v1.ListApiKeysRequest\x1a .boxd.api.v1.ListApiKeysResponse\x12S\n\x0c\x44\x65leteApiKey\x12 .boxd.api.v1.DeleteApiKeyRequest\x1a!.boxd.api.v1.DeleteApiKeyResponseb\x06proto3')
28
+
29
+ _globals = globals()
30
+ _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
31
+ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'api_pb2', _globals)
32
+ if not _descriptor._USE_C_DESCRIPTORS:
33
+ DESCRIPTOR._loaded_options = None
34
+ _globals['_VMCONFIG']._serialized_start=27
35
+ _globals['_VMCONFIG']._serialized_end=218
36
+ _globals['_SRFCONFIG']._serialized_start=220
37
+ _globals['_SRFCONFIG']._serialized_end=336
38
+ _globals['_NETWORKCONFIG']._serialized_start=338
39
+ _globals['_NETWORKCONFIG']._serialized_end=408
40
+ _globals['_PROXYENTRY']._serialized_start=410
41
+ _globals['_PROXYENTRY']._serialized_end=450
42
+ _globals['_VOLUMEMOUNT']._serialized_start=452
43
+ _globals['_VOLUMEMOUNT']._serialized_end=521
44
+ _globals['_CREATEVMREQUEST']._serialized_start=524
45
+ _globals['_CREATEVMREQUEST']._serialized_end=696
46
+ _globals['_ENVVAR']._serialized_start=698
47
+ _globals['_ENVVAR']._serialized_end=734
48
+ _globals['_CREATEVMRESPONSE']._serialized_start=737
49
+ _globals['_CREATEVMRESPONSE']._serialized_end=869
50
+ _globals['_DESTROYVMREQUEST']._serialized_start=871
51
+ _globals['_DESTROYVMREQUEST']._serialized_end=904
52
+ _globals['_DESTROYVMRESPONSE']._serialized_start=906
53
+ _globals['_DESTROYVMRESPONSE']._serialized_end=925
54
+ _globals['_STARTVMREQUEST']._serialized_start=927
55
+ _globals['_STARTVMREQUEST']._serialized_end=958
56
+ _globals['_STARTVMRESPONSE']._serialized_start=960
57
+ _globals['_STARTVMRESPONSE']._serialized_end=977
58
+ _globals['_STOPVMREQUEST']._serialized_start=979
59
+ _globals['_STOPVMREQUEST']._serialized_end=1009
60
+ _globals['_STOPVMRESPONSE']._serialized_start=1011
61
+ _globals['_STOPVMRESPONSE']._serialized_end=1027
62
+ _globals['_REBOOTVMREQUEST']._serialized_start=1029
63
+ _globals['_REBOOTVMREQUEST']._serialized_end=1061
64
+ _globals['_REBOOTVMRESPONSE']._serialized_start=1063
65
+ _globals['_REBOOTVMRESPONSE']._serialized_end=1081
66
+ _globals['_SUSPENDVMREQUEST']._serialized_start=1083
67
+ _globals['_SUSPENDVMREQUEST']._serialized_end=1116
68
+ _globals['_SUSPENDVMRESPONSE']._serialized_start=1118
69
+ _globals['_SUSPENDVMRESPONSE']._serialized_end=1157
70
+ _globals['_RESUMEVMREQUEST']._serialized_start=1159
71
+ _globals['_RESUMEVMREQUEST']._serialized_end=1191
72
+ _globals['_RESUMEVMRESPONSE']._serialized_start=1193
73
+ _globals['_RESUMEVMRESPONSE']._serialized_end=1230
74
+ _globals['_GETVMREQUEST']._serialized_start=1232
75
+ _globals['_GETVMREQUEST']._serialized_end=1261
76
+ _globals['_GETVMRESPONSE']._serialized_start=1264
77
+ _globals['_GETVMRESPONSE']._serialized_end=1441
78
+ _globals['_LISTVMSREQUEST']._serialized_start=1443
79
+ _globals['_LISTVMSREQUEST']._serialized_end=1459
80
+ _globals['_LISTVMSRESPONSE']._serialized_start=1461
81
+ _globals['_LISTVMSRESPONSE']._serialized_end=1519
82
+ _globals['_STREAMLOGSREQUEST']._serialized_start=1521
83
+ _globals['_STREAMLOGSREQUEST']._serialized_end=1571
84
+ _globals['_LOGCHUNK']._serialized_start=1573
85
+ _globals['_LOGCHUNK']._serialized_end=1597
86
+ _globals['_EXECCHUNK']._serialized_start=1599
87
+ _globals['_EXECCHUNK']._serialized_end=1703
88
+ _globals['_CREATENETWORKREQUEST']._serialized_start=1705
89
+ _globals['_CREATENETWORKREQUEST']._serialized_end=1741
90
+ _globals['_CREATENETWORKRESPONSE']._serialized_start=1743
91
+ _globals['_CREATENETWORKRESPONSE']._serialized_end=1786
92
+ _globals['_LISTNETWORKSREQUEST']._serialized_start=1788
93
+ _globals['_LISTNETWORKSREQUEST']._serialized_end=1809
94
+ _globals['_LISTNETWORKSRESPONSE']._serialized_start=1811
95
+ _globals['_LISTNETWORKSRESPONSE']._serialized_end=1877
96
+ _globals['_NETWORKINFO']._serialized_start=1879
97
+ _globals['_NETWORKINFO']._serialized_end=1944
98
+ _globals['_BINDDOMAINREQUEST']._serialized_start=1946
99
+ _globals['_BINDDOMAINREQUEST']._serialized_end=1996
100
+ _globals['_BINDDOMAINRESPONSE']._serialized_start=1998
101
+ _globals['_BINDDOMAINRESPONSE']._serialized_end=2018
102
+ _globals['_UNBINDDOMAINREQUEST']._serialized_start=2020
103
+ _globals['_UNBINDDOMAINREQUEST']._serialized_end=2057
104
+ _globals['_UNBINDDOMAINRESPONSE']._serialized_start=2059
105
+ _globals['_UNBINDDOMAINRESPONSE']._serialized_end=2081
106
+ _globals['_LISTDOMAINSREQUEST']._serialized_start=2083
107
+ _globals['_LISTDOMAINSREQUEST']._serialized_end=2103
108
+ _globals['_LISTDOMAINSRESPONSE']._serialized_start=2105
109
+ _globals['_LISTDOMAINSRESPONSE']._serialized_end=2168
110
+ _globals['_DOMAININFO']._serialized_start=2170
111
+ _globals['_DOMAININFO']._serialized_end=2213
112
+ _globals['_GETCONFIGREQUEST']._serialized_start=2215
113
+ _globals['_GETCONFIGREQUEST']._serialized_end=2233
114
+ _globals['_GETCONFIGRESPONSE']._serialized_start=2235
115
+ _globals['_GETCONFIGRESPONSE']._serialized_end=2291
116
+ _globals['_WHOAMIREQUEST']._serialized_start=2293
117
+ _globals['_WHOAMIREQUEST']._serialized_end=2308
118
+ _globals['_WHOAMIRESPONSE']._serialized_start=2310
119
+ _globals['_WHOAMIRESPONSE']._serialized_end=2400
120
+ _globals['_CREATETOKENREQUEST']._serialized_start=2402
121
+ _globals['_CREATETOKENREQUEST']._serialized_end=2447
122
+ _globals['_CREATETOKENRESPONSE']._serialized_start=2449
123
+ _globals['_CREATETOKENRESPONSE']._serialized_end=2505
124
+ _globals['_LISTTOKENSREQUEST']._serialized_start=2507
125
+ _globals['_LISTTOKENSREQUEST']._serialized_end=2526
126
+ _globals['_LISTTOKENSRESPONSE']._serialized_start=2528
127
+ _globals['_LISTTOKENSRESPONSE']._serialized_end=2588
128
+ _globals['_TOKENINFO']._serialized_start=2590
129
+ _globals['_TOKENINFO']._serialized_end=2654
130
+ _globals['_REVOKETOKENREQUEST']._serialized_start=2656
131
+ _globals['_REVOKETOKENREQUEST']._serialized_end=2689
132
+ _globals['_REVOKETOKENRESPONSE']._serialized_start=2691
133
+ _globals['_REVOKETOKENRESPONSE']._serialized_end=2712
134
+ _globals['_FORKVMREQUEST']._serialized_start=2714
135
+ _globals['_FORKVMREQUEST']._serialized_end=2804
136
+ _globals['_FORKVMRESPONSE']._serialized_start=2807
137
+ _globals['_FORKVMRESPONSE']._serialized_end=2958
138
+ _globals['_LISTPROXIESREQUEST']._serialized_start=2960
139
+ _globals['_LISTPROXIESREQUEST']._serialized_end=2997
140
+ _globals['_LISTPROXIESRESPONSE']._serialized_start=2999
141
+ _globals['_LISTPROXIESRESPONSE']._serialized_end=3061
142
+ _globals['_PROXYINFO']._serialized_start=3063
143
+ _globals['_PROXYINFO']._serialized_end=3177
144
+ _globals['_CREATEPROXYREQUEST']._serialized_start=3179
145
+ _globals['_CREATEPROXYREQUEST']._serialized_end=3244
146
+ _globals['_CREATEPROXYRESPONSE']._serialized_start=3246
147
+ _globals['_CREATEPROXYRESPONSE']._serialized_end=3328
148
+ _globals['_DELETEPROXYREQUEST']._serialized_start=3330
149
+ _globals['_DELETEPROXYREQUEST']._serialized_end=3381
150
+ _globals['_DELETEPROXYRESPONSE']._serialized_start=3383
151
+ _globals['_DELETEPROXYRESPONSE']._serialized_end=3404
152
+ _globals['_SETPROXYPORTREQUEST']._serialized_start=3406
153
+ _globals['_SETPROXYPORTREQUEST']._serialized_end=3472
154
+ _globals['_SETPROXYPORTRESPONSE']._serialized_start=3474
155
+ _globals['_SETPROXYPORTRESPONSE']._serialized_end=3496
156
+ _globals['_UPLOADFILEREQUEST']._serialized_start=3498
157
+ _globals['_UPLOADFILEREQUEST']._serialized_end=3560
158
+ _globals['_UPLOADFILERESPONSE']._serialized_start=3562
159
+ _globals['_UPLOADFILERESPONSE']._serialized_end=3582
160
+ _globals['_DOWNLOADFILEREQUEST']._serialized_start=3584
161
+ _globals['_DOWNLOADFILEREQUEST']._serialized_end=3634
162
+ _globals['_DOWNLOADFILERESPONSE']._serialized_start=3636
163
+ _globals['_DOWNLOADFILERESPONSE']._serialized_end=3672
164
+ _globals['_CREATETEMPLATEREQUEST']._serialized_start=3674
165
+ _globals['_CREATETEMPLATEREQUEST']._serialized_end=3769
166
+ _globals['_CREATETEMPLATERESPONSE']._serialized_start=3771
167
+ _globals['_CREATETEMPLATERESPONSE']._serialized_end=3846
168
+ _globals['_LISTTEMPLATESREQUEST']._serialized_start=3848
169
+ _globals['_LISTTEMPLATESREQUEST']._serialized_end=3870
170
+ _globals['_LISTTEMPLATESRESPONSE']._serialized_start=3872
171
+ _globals['_LISTTEMPLATESRESPONSE']._serialized_end=3941
172
+ _globals['_TEMPLATEINFO']._serialized_start=3943
173
+ _globals['_TEMPLATEINFO']._serialized_end=4063
174
+ _globals['_DELETETEMPLATEREQUEST']._serialized_start=4065
175
+ _globals['_DELETETEMPLATEREQUEST']._serialized_end=4109
176
+ _globals['_DELETETEMPLATERESPONSE']._serialized_start=4111
177
+ _globals['_DELETETEMPLATERESPONSE']._serialized_end=4135
178
+ _globals['_CREATEVMFROMTEMPLATEREQUEST']._serialized_start=4137
179
+ _globals['_CREATEVMFROMTEMPLATEREQUEST']._serialized_end=4240
180
+ _globals['_CREATEVMFROMTEMPLATERESPONSE']._serialized_start=4243
181
+ _globals['_CREATEVMFROMTEMPLATERESPONSE']._serialized_end=4372
182
+ _globals['_CREATEDISKREQUEST']._serialized_start=4374
183
+ _globals['_CREATEDISKREQUEST']._serialized_end=4427
184
+ _globals['_CREATEDISKRESPONSE']._serialized_start=4429
185
+ _globals['_CREATEDISKRESPONSE']._serialized_end=4516
186
+ _globals['_LISTDISKSREQUEST']._serialized_start=4518
187
+ _globals['_LISTDISKSREQUEST']._serialized_end=4536
188
+ _globals['_LISTDISKSRESPONSE']._serialized_start=4538
189
+ _globals['_LISTDISKSRESPONSE']._serialized_end=4595
190
+ _globals['_DISKINFO']._serialized_start=4598
191
+ _globals['_DISKINFO']._serialized_end=4744
192
+ _globals['_DISKATTACHMENT']._serialized_start=4746
193
+ _globals['_DISKATTACHMENT']._serialized_end=4834
194
+ _globals['_ATTACHDISKREQUEST']._serialized_start=4836
195
+ _globals['_ATTACHDISKREQUEST']._serialized_end=4926
196
+ _globals['_ATTACHDISKRESPONSE']._serialized_start=4928
197
+ _globals['_ATTACHDISKRESPONSE']._serialized_end=4948
198
+ _globals['_DETACHDISKREQUEST']._serialized_start=4950
199
+ _globals['_DETACHDISKREQUEST']._serialized_end=5001
200
+ _globals['_DETACHDISKRESPONSE']._serialized_start=5003
201
+ _globals['_DETACHDISKRESPONSE']._serialized_end=5023
202
+ _globals['_DESTROYDISKREQUEST']._serialized_start=5025
203
+ _globals['_DESTROYDISKREQUEST']._serialized_end=5062
204
+ _globals['_DESTROYDISKRESPONSE']._serialized_start=5064
205
+ _globals['_DESTROYDISKRESPONSE']._serialized_end=5085
206
+ _globals['_SETAUTOSUSPENDTIMEOUTREQUEST']._serialized_start=5087
207
+ _globals['_SETAUTOSUSPENDTIMEOUTREQUEST']._serialized_end=5154
208
+ _globals['_SETAUTOSUSPENDTIMEOUTRESPONSE']._serialized_start=5156
209
+ _globals['_SETAUTOSUSPENDTIMEOUTRESPONSE']._serialized_end=5187
210
+ _globals['_CREATEAPIKEYREQUEST']._serialized_start=5189
211
+ _globals['_CREATEAPIKEYREQUEST']._serialized_end=5249
212
+ _globals['_CREATEAPIKEYRESPONSE']._serialized_start=5251
213
+ _globals['_CREATEAPIKEYRESPONSE']._serialized_end=5322
214
+ _globals['_LISTAPIKEYSREQUEST']._serialized_start=5324
215
+ _globals['_LISTAPIKEYSREQUEST']._serialized_end=5344
216
+ _globals['_LISTAPIKEYSRESPONSE']._serialized_start=5346
217
+ _globals['_LISTAPIKEYSRESPONSE']._serialized_end=5406
218
+ _globals['_APIKEYINFO']._serialized_start=5408
219
+ _globals['_APIKEYINFO']._serialized_end=5528
220
+ _globals['_DELETEAPIKEYREQUEST']._serialized_start=5530
221
+ _globals['_DELETEAPIKEYREQUEST']._serialized_end=5563
222
+ _globals['_DELETEAPIKEYRESPONSE']._serialized_start=5565
223
+ _globals['_DELETEAPIKEYRESPONSE']._serialized_end=5587
224
+ _globals['_BOXDAPI']._serialized_start=5590
225
+ _globals['_BOXDAPI']._serialized_end=8877
226
+ # @@protoc_insertion_point(module_scope)
@@ -194,6 +194,11 @@ class BoxdApiStub(object):
194
194
  request_serializer=api__pb2.CreateVmFromTemplateRequest.SerializeToString,
195
195
  response_deserializer=api__pb2.CreateVmFromTemplateResponse.FromString,
196
196
  _registered_method=True)
197
+ self.SetAutoSuspendTimeout = channel.unary_unary(
198
+ '/boxd.api.v1.BoxdApi/SetAutoSuspendTimeout',
199
+ request_serializer=api__pb2.SetAutoSuspendTimeoutRequest.SerializeToString,
200
+ response_deserializer=api__pb2.SetAutoSuspendTimeoutResponse.FromString,
201
+ _registered_method=True)
197
202
  self.CreateDisk = channel.unary_unary(
198
203
  '/boxd.api.v1.BoxdApi/CreateDisk',
199
204
  request_serializer=api__pb2.CreateDiskRequest.SerializeToString,
@@ -431,6 +436,12 @@ class BoxdApiServicer(object):
431
436
  context.set_details('Method not implemented!')
432
437
  raise NotImplementedError('Method not implemented!')
433
438
 
439
+ def SetAutoSuspendTimeout(self, request, context):
440
+ """Missing associated documentation comment in .proto file."""
441
+ context.set_code(grpc.StatusCode.UNIMPLEMENTED)
442
+ context.set_details('Method not implemented!')
443
+ raise NotImplementedError('Method not implemented!')
444
+
434
445
  def CreateDisk(self, request, context):
435
446
  """Disks
436
447
  """
@@ -644,6 +655,11 @@ def add_BoxdApiServicer_to_server(servicer, server):
644
655
  request_deserializer=api__pb2.CreateVmFromTemplateRequest.FromString,
645
656
  response_serializer=api__pb2.CreateVmFromTemplateResponse.SerializeToString,
646
657
  ),
658
+ 'SetAutoSuspendTimeout': grpc.unary_unary_rpc_method_handler(
659
+ servicer.SetAutoSuspendTimeout,
660
+ request_deserializer=api__pb2.SetAutoSuspendTimeoutRequest.FromString,
661
+ response_serializer=api__pb2.SetAutoSuspendTimeoutResponse.SerializeToString,
662
+ ),
647
663
  'CreateDisk': grpc.unary_unary_rpc_method_handler(
648
664
  servicer.CreateDisk,
649
665
  request_deserializer=api__pb2.CreateDiskRequest.FromString,
@@ -1559,6 +1575,33 @@ class BoxdApi(object):
1559
1575
  metadata,
1560
1576
  _registered_method=True)
1561
1577
 
1578
+ @staticmethod
1579
+ def SetAutoSuspendTimeout(request,
1580
+ target,
1581
+ options=(),
1582
+ channel_credentials=None,
1583
+ call_credentials=None,
1584
+ insecure=False,
1585
+ compression=None,
1586
+ wait_for_ready=None,
1587
+ timeout=None,
1588
+ metadata=None):
1589
+ return grpc.experimental.unary_unary(
1590
+ request,
1591
+ target,
1592
+ '/boxd.api.v1.BoxdApi/SetAutoSuspendTimeout',
1593
+ api__pb2.SetAutoSuspendTimeoutRequest.SerializeToString,
1594
+ api__pb2.SetAutoSuspendTimeoutResponse.FromString,
1595
+ options,
1596
+ channel_credentials,
1597
+ insecure,
1598
+ call_credentials,
1599
+ compression,
1600
+ wait_for_ready,
1601
+ timeout,
1602
+ metadata,
1603
+ _registered_method=True)
1604
+
1562
1605
  @staticmethod
1563
1606
  def CreateDisk(request,
1564
1607
  target,
@@ -411,6 +411,7 @@ class Compute(_SyncBase):
411
411
  token: str | None = None,
412
412
  api_url: str | None = None,
413
413
  exchange_url: str | None = None,
414
+ environment: str | None = None,
414
415
  ) -> None:
415
416
  from .client import Compute as AsyncCompute
416
417
 
@@ -420,6 +421,7 @@ class Compute(_SyncBase):
420
421
  token=token,
421
422
  api_url=api_url,
422
423
  exchange_url=exchange_url,
424
+ environment=environment,
423
425
  )
424
426
  self.box = BoxService(self._async.box, self._loop)
425
427
  self.template = TemplateService(self._async.template, self._loop)
@@ -0,0 +1,169 @@
1
+ """SDK update notice — piggybacks on every gRPC call's metadata.
2
+
3
+ The proxy attaches `x-boxd-py-sdk-latest` to response initial metadata when
4
+ a newer SDK version is available. We send `x-boxd-py-sdk-version` outbound
5
+ so the server can log who's calling. On the first response that carries a
6
+ strictly-newer latest version, we print a one-time stderr nag.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import re
12
+ import sys
13
+
14
+ import grpc
15
+ import grpc.aio
16
+
17
+ REQ_HEADER = "x-boxd-py-sdk-version"
18
+ RESP_HEADER = "x-boxd-py-sdk-latest"
19
+ UPGRADE_CMD = "pip install --upgrade boxd"
20
+
21
+ _notified = False
22
+
23
+
24
+ def _current_version() -> str:
25
+ # Late import so this module is importable from inside the package
26
+ # without circular-import drama (boxd/__init__.py imports a lot).
27
+ from . import __version__
28
+
29
+ return __version__
30
+
31
+
32
+ class VersionCheckInterceptor(
33
+ grpc.aio.UnaryUnaryClientInterceptor,
34
+ grpc.aio.UnaryStreamClientInterceptor,
35
+ grpc.aio.StreamUnaryClientInterceptor,
36
+ grpc.aio.StreamStreamClientInterceptor,
37
+ ):
38
+ """Adds outbound SDK-version header, watches inbound for an upgrade hint."""
39
+
40
+ def _add_version(self, client_call_details):
41
+ metadata = list(client_call_details.metadata or [])
42
+ metadata.append((REQ_HEADER, _current_version()))
43
+ return client_call_details._replace(metadata=metadata)
44
+
45
+ async def _maybe_notify_from_call(self, call):
46
+ global _notified
47
+ if _notified:
48
+ return
49
+ try:
50
+ md = await call.initial_metadata()
51
+ except Exception:
52
+ return
53
+ if md is None:
54
+ return
55
+ latest = None
56
+ for key, value in md:
57
+ if key.lower() == RESP_HEADER:
58
+ latest = value.strip() if isinstance(value, str) else None
59
+ break
60
+ if not latest:
61
+ return
62
+ current = _current_version()
63
+ if _compare_semver(latest, current) <= 0:
64
+ return
65
+ _notified = True
66
+ print(file=sys.stderr)
67
+ print(
68
+ f" A new version of boxd is available (v{latest}, you have v{current}). Update with:",
69
+ file=sys.stderr,
70
+ )
71
+ print(f" {UPGRADE_CMD}", file=sys.stderr)
72
+
73
+ async def intercept_unary_unary(self, continuation, client_call_details, request):
74
+ new_details = self._add_version(client_call_details)
75
+ call = await continuation(new_details, request)
76
+ await self._maybe_notify_from_call(call)
77
+ return call
78
+
79
+ async def intercept_unary_stream(self, continuation, client_call_details, request):
80
+ new_details = self._add_version(client_call_details)
81
+ call = await continuation(new_details, request)
82
+ await self._maybe_notify_from_call(call)
83
+ return call
84
+
85
+ async def intercept_stream_unary(
86
+ self, continuation, client_call_details, request_iterator
87
+ ):
88
+ new_details = self._add_version(client_call_details)
89
+ call = await continuation(new_details, request_iterator)
90
+ await self._maybe_notify_from_call(call)
91
+ return call
92
+
93
+ async def intercept_stream_stream(
94
+ self, continuation, client_call_details, request_iterator
95
+ ):
96
+ new_details = self._add_version(client_call_details)
97
+ call = await continuation(new_details, request_iterator)
98
+ await self._maybe_notify_from_call(call)
99
+ return call
100
+
101
+
102
+ _SEMVER_RE = re.compile(r"^(\d+)\.(\d+)\.(\d+)(.*)$")
103
+ _SUFFIX_SEPARATORS_RE = re.compile(r"[.-]")
104
+ _SUFFIX_LETTER_DIGIT_RE = re.compile(r"(?<=\D)(?=\d)|(?<=\d)(?=\D)")
105
+
106
+
107
+ def _compare_semver(a: str, b: str) -> int:
108
+ """Return >0 if a > b, <0 if a < b, 0 if equal/unparseable.
109
+
110
+ Handles pre-release suffixes ("0.1.1-dev.4", "0.1.1.dev4") by
111
+ component-wise compare, numeric where both components are all-digits.
112
+ A release (no suffix) ranks above any pre-release of the same
113
+ numeric prefix. Unparseable input returns 0 — never nag on garbage.
114
+ """
115
+ pa = _SEMVER_RE.match(a.strip())
116
+ pb = _SEMVER_RE.match(b.strip())
117
+ if not pa or not pb:
118
+ return 0
119
+ for i in range(1, 4):
120
+ ai, bi = int(pa.group(i)), int(pb.group(i))
121
+ if ai != bi:
122
+ return ai - bi
123
+ sa, sb = pa.group(4) or "", pb.group(4) or ""
124
+ if sa == "" and sb != "":
125
+ return 1
126
+ if sa != "" and sb == "":
127
+ return -1
128
+ return _compare_suffix(sa, sb)
129
+
130
+
131
+ def _compare_suffix(a: str, b: str) -> int:
132
+ if a == b:
133
+ return 0
134
+ parts_a = _parse_suffix(a)
135
+ parts_b = _parse_suffix(b)
136
+ for i in range(max(len(parts_a), len(parts_b))):
137
+ pa = parts_a[i] if i < len(parts_a) else None
138
+ pb = parts_b[i] if i < len(parts_b) else None
139
+ if pa is None:
140
+ return -1 # shorter prerelease ranks lower
141
+ if pb is None:
142
+ return 1
143
+ na = int(pa) if pa.isdigit() else None
144
+ nb = int(pb) if pb.isdigit() else None
145
+ if na is not None and nb is not None:
146
+ if na != nb:
147
+ return na - nb
148
+ elif na is not None:
149
+ return -1 # numeric < alphanumeric (SemVer §11.4.3)
150
+ elif nb is not None:
151
+ return 1
152
+ elif pa != pb:
153
+ return -1 if pa < pb else 1
154
+ return 0
155
+
156
+
157
+ def _parse_suffix(s: str) -> list[str]:
158
+ """Decompose "-dev.6" / ".dev6" into ["dev", "6"]."""
159
+ if not s:
160
+ return []
161
+ stripped = s.lstrip("-.")
162
+ if not stripped:
163
+ return []
164
+ components: list[str] = []
165
+ for piece in _SUFFIX_SEPARATORS_RE.split(stripped):
166
+ if not piece:
167
+ continue
168
+ components.extend(p for p in _SUFFIX_LETTER_DIGIT_RE.split(piece) if p)
169
+ return components