vxsdk 0.1.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.
@@ -0,0 +1,287 @@
1
+ Metadata-Version: 2.4
2
+ Name: vxsdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for the vxcloud / VxCloud platform — provision infrastructure, deploy applications, and manage running services from your terminal or CI pipeline.
5
+ Author-email: vxcloud <engineering@vxcloud.io>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://vxcloud.io
8
+ Project-URL: Documentation, https://vxcloud.io/docs/sdks
9
+ Project-URL: Repository, https://github.com/vxcloud/platform
10
+ Project-URL: Issues, https://github.com/vxcloud/platform/issues
11
+ Project-URL: Changelog, https://github.com/vxcloud/platform/blob/main/services/sdk/python/CHANGELOG.md
12
+ Keywords: vxcloud,vxcloud,vxcli,infrastructure,iac,deploy,ssh,docker,kubernetes,ai-agents
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: License :: OSI Approved :: Apache Software License
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Classifier: Topic :: System :: Systems Administration
25
+ Classifier: Topic :: System :: Installation/Setup
26
+ Requires-Python: >=3.9
27
+ Description-Content-Type: text/markdown
28
+ Provides-Extra: async
29
+ Requires-Dist: httpx>=0.25; extra == "async"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest>=7; extra == "dev"
32
+ Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
33
+ Requires-Dist: httpx>=0.25; extra == "dev"
34
+ Requires-Dist: build>=1.0; extra == "dev"
35
+ Requires-Dist: twine>=4.0; extra == "dev"
36
+
37
+ # vxsdk (Python, preview)
38
+
39
+ Single-file, stdlib-only Python port of [`../`](..) — the Go SDK.
40
+
41
+ Same wire contract, same auth model (API key + auto-refresh on 401),
42
+ same resource layout. Use this from Python scripts, Jupyter notebooks,
43
+ data pipelines, or any internal Python service that needs to talk to
44
+ the vxcloud platform.
45
+
46
+ ```
47
+ services/sdk/python/
48
+ ├── vxsdk.py sync SDK — stdlib only, drop-in
49
+ ├── vxsdk_async.py async SDK — same API, requires httpx
50
+ ├── deploy_app.py runnable sync demo (container or stack)
51
+ ├── deploy_async.py runnable async demo (3 deploys in parallel)
52
+ └── README.md this file
53
+ ```
54
+
55
+ ## Two flavors
56
+
57
+ | Flavor | Module | Dependency | When to use |
58
+ |---|---|---|---|
59
+ | **Sync** | `vxsdk` | stdlib only | Scripts, notebooks, single-shot operations, simple migrations from `vxcli` |
60
+ | **Async** | `vxsdk_async` | `httpx` (`pip install httpx`) | FastAPI / aiohttp services, concurrent fan-out (multi-host deploys, batch installs), high-throughput integration |
61
+
62
+ Same class hierarchy, same method signatures, same auth model. Switching
63
+ is essentially `vxsdk.Client` → `vxsdk_async.AsyncClient` plus
64
+ `async`/`await`.
65
+
66
+ ## Why a parallel Python implementation?
67
+
68
+ Python and Go don't share runtimes. The Go SDK is the right answer for
69
+ Go services and customers; this Python file is the right answer for
70
+ Python customers. Both are wrappers over the same FastAPI HTTP surface,
71
+ so the JSON wire is identical and they can be regenerated from a single
72
+ OpenAPI spec when the platform team enables one.
73
+
74
+ For now, both are hand-written and kept in sync by review.
75
+
76
+ ## Installation
77
+
78
+ ```bash
79
+ # PyPI (canonical name)
80
+ pip install vxsdk
81
+ pip install vxsdk[async] # adds httpx for vxsdk_async
82
+
83
+ # PyPI (brand-name alias — same code, just `import vxcloud`)
84
+ pip install vxcloud
85
+ pip install vxcloud[async]
86
+
87
+ # Drop-in (no install, stdlib-only)
88
+ cp services/sdk/python/vxsdk.py /path/to/your/project/
89
+ ```
90
+
91
+ Stdlib only for the sync flavor — no extra deps. Tested on Python 3.9+.
92
+
93
+ ## Entry-point styles
94
+
95
+ All four below resolve to the same class object — pick the name you and
96
+ your team prefer. There is no behavior difference:
97
+
98
+ ```python
99
+ import vxsdk
100
+
101
+ c = vxsdk.Client.load_from_vxcli() # canonical
102
+ c = vxsdk.VxCloud.load_from_vxcli() # PascalCase brand (matches TS SDK)
103
+ c = vxsdk.vxcloud.load_from_vxcli() # lowercase brand
104
+
105
+ # Or via the alias package:
106
+ import vxcloud
107
+ c = vxcloud.Client.load_from_vxcli()
108
+ c = vxcloud.load_from_vxcli() # module-level convenience
109
+ ```
110
+
111
+ ## Quick start
112
+
113
+ ```python
114
+ import vxsdk
115
+
116
+ # Reads ~/.vxcloud/credentials.json (the file `vxcli auth login` writes)
117
+ c = vxsdk.Client.load_from_vxcli()
118
+
119
+ # Or with explicit credentials
120
+ # c = vxsdk.Client(api_key="xc_dev_...", username="alice")
121
+
122
+ # Provision a VM — `c.cloud.vm.provision(...)` mirrors the TypeScript SDK.
123
+ # (The legacy flat `c.cloud.create_vm(...)` also still works.)
124
+ vm = c.cloud.vm.provision(
125
+ name="api-vm", cloud="aws", region="us-east-1",
126
+ instance_type="t3.small", key_pair_name="AWSPRODKEY2",
127
+ )
128
+ print(vm["public_ip"])
129
+
130
+ # Deploy FastAPI onto the new VM
131
+ sess = c.deploy.fastapi(
132
+ path="./", entry="app.app:app",
133
+ requirements="requirements.txt",
134
+ app_port=8000, http_port=80, app_name="studio-backend",
135
+ host=vm["public_ip"], ssh_user="ubuntu",
136
+ key_pair_name="AWSPRODKEY1.PEM",
137
+ )
138
+ print(sess["session_id"])
139
+
140
+ # Deploy a Docker container onto a VM
141
+ result = c.deploy.container(
142
+ host="54.197.71.181", ssh_user="ubuntu", key_pair_name="AWSPRODKEY1.PEM",
143
+ image="grafana/grafana:latest",
144
+ name="grafana", ports=["3000:3000"],
145
+ restart_policy="unless-stopped",
146
+ )
147
+ print(result["session_id"], result.get("status"))
148
+
149
+ # Deploy a language stack from a public git repo
150
+ result = c.deploy.stack(
151
+ "golang",
152
+ host="54.197.71.181", ssh_user="ubuntu", key_pair_name="AWSPRODKEY1.PEM",
153
+ repo_url="https://github.com/joelwembo/va-sample-golang.git", branch="main",
154
+ git_provider="github", app_name="va-sample-golang",
155
+ http_port="80", app_port="8080", go_version="1.22",
156
+ )
157
+
158
+ # Run a custom shell script over SSH
159
+ result = c.install.script(
160
+ host="54.197.71.181", ssh_user="ubuntu", key_pair_name="AWSPRODKEY1.PEM",
161
+ script="#!/bin/bash\necho hello\n",
162
+ script_name="hello.sh",
163
+ )
164
+
165
+ # CI/CD
166
+ for p in c.cicd.pipelines.list():
167
+ print(p["id"], p["name"], p.get("repository_url"))
168
+
169
+ build = c.cicd.pipelines.trigger(pipeline_id="abc...", branch="main")
170
+
171
+ # Marketplace
172
+ agents = c.marketplace.agents.list()
173
+ result = c.marketplace.agents.deploy(
174
+ "golang_url_status_agent",
175
+ host="54.197.71.181", ssh_user="ubuntu", key_pair_name="AWSPRODKEY1.PEM",
176
+ http_port="8094",
177
+ )
178
+
179
+ # Cloud provisioning (real AWS resources)
180
+ result = c.cloud.create_s3_bucket("my-bucket-001", region="us-east-1")
181
+ result = c.cloud.create_iam_policy("my-policy-001",
182
+ policy_document={"Version": "2012-10-17", "Statement": [...]})
183
+ ```
184
+
185
+ ## Resource map
186
+
187
+ | Path | Method | Backend endpoint |
188
+ |---|---|---|
189
+ | `c.cicd.pipelines.list/show/trigger` | GET/GET/POST | `/api/v2/cicd/pipelines/...` |
190
+ | `c.cicd.builds.show` | GET | `/api/v2/cicd/builds/{id}` |
191
+ | `c.sessions.list` | GET | `/api/v3/sessions/list` |
192
+ | `c.install.script` | POST multipart | `/api/v2/tenant/install/script` |
193
+ | `c.install.compose` | POST multipart | `/api/v2/tenant/provision/docker-compose/custom` |
194
+ | `c.deploy.container` | POST multipart | `/api/v2/tenant/container/deploy` |
195
+ | `c.deploy.stack(kind)` | POST multipart | `/api/v2/infrastructure/services/<kind>/deploy` |
196
+ | `c.marketplace.agents.list/show/deploy` | GET/GET/POST | `/api/v2/marketplace/agents/...` |
197
+ | `c.marketplace.models.list/show` | GET/GET | `/api/v2/marketplace/models/...` |
198
+ | `c.marketplace.solutions.list/show/provision` | GET/GET/POST | `/api/v2/marketplace/templates`, `/provision` |
199
+ | `c.cloud.create_s3_bucket` | POST | `/api/v2/tenant/provision/storage` |
200
+ | `c.cloud.create_iam_policy/role/keypair` | POST | `/api/v2/tenant/provision/security` |
201
+ | `c.cloud.create_vm` *(legacy)* | POST | `/api/v2/tenant/provision/vm` |
202
+ | `c.cloud.vm.provision/status/action` | POST | `/api/v2/tenant/provision/vm`, `/provision/vm/{status,action}` |
203
+ | `c.cloud.create_vpc` | POST | `/api/v2/tenant/provision/networks` |
204
+ | `c.cloud.create_kubernetes_cluster` | POST | `/api/v2/tenant/provision/kubernetes` |
205
+ | `c.cloud.list_kubernetes_clusters` | GET | `/api/v2/tenant/kubernetes/clusters` |
206
+ | `c.cloud.kubernetes_cluster_details` | POST | `/api/v2/tenant/kubernetes/cluster/details` |
207
+ | `c.cloud.create_serverless_function` | POST | `/api/v2/tenant/provision/serverless` |
208
+ | `c.metaldb.test_connection/provision` | POST | `/api/v2/tenant/metaldb/...` |
209
+ | `c.nodes.list/default/set_default` | GET/POST | `/api/v1/auth/nodes/` (control plane) |
210
+ | `c.workspace.delete_workspace` | DELETE | `/api/v2/setup/workspace` |
211
+ | `c.marketplace.models.deploy` | POST | `/api/v2/marketplace/models/deploy` |
212
+ | `c.agentcontrol.{summary,fine_tuning,training,knowledge,datasets,agents,github}` | GET/POST | `/api/v2/agentcontrol/...` (X-Tenant-ID header) |
213
+ | `c.vxcomputer.info/run/classify/audit_verify` | GET/POST | `/api/v2/vxcomputer/...` |
214
+ | `c.workflow.list/create/validate/execute/export` | GET/POST | `/api/v2/workflow/...` |
215
+ | `c.vxchrono.create_goal/schedule/launch_run` | POST | `/api/v2/vxchrono/...` |
216
+ | `c.robotic.list_robots/register_robot/send_command` | GET/POST | `/api/v2/robotic/...` |
217
+
218
+ Async parity: `vxsdk_async.AsyncClient` exposes the same modules,
219
+ including `c.vxcomputer`, `c.workflow`, `c.vxchrono`, and `c.robotic`.
220
+
221
+ ## Errors
222
+
223
+ ```python
224
+ try:
225
+ c.cicd.pipelines.list()
226
+ except vxsdk.VxAuthError as e: # 401/403
227
+ ...
228
+ except vxsdk.VxValidationError as e: # 400/422
229
+ ...
230
+ except vxsdk.VxRateLimitError as e: # 429 — e.retry_after
231
+ ...
232
+ except vxsdk.VxNotFoundError as e: # 404
233
+ ...
234
+ except vxsdk.VxServerError as e: # 5xx
235
+ ...
236
+ except vxsdk.VxNetworkError as e: # transport
237
+ ...
238
+ except vxsdk.VxError as e: # base, anything else
239
+ ...
240
+ ```
241
+
242
+ The SDK retries `VxNetworkError`, `VxServerError`, and `VxRateLimitError`
243
+ up to 3 times with exponential backoff. Auth errors and validation errors
244
+ are surfaced immediately — retrying them as-is would not succeed.
245
+
246
+ On `401`, the SDK calls `POST /api/v1/auth/developer/keys/login` once
247
+ with the configured API key, replays the original request, and only
248
+ surfaces the error if the refresh itself fails. Application code should
249
+ not see token expiration.
250
+
251
+ ## Run the sync deploy program
252
+
253
+ ```bash
254
+ cd services/sdk/python
255
+ python3 deploy_app.py # whoami container on inst3:8085
256
+ python3 deploy_app.py --image redis:7 --name r --ports 6380:6379
257
+ python3 deploy_app.py --mode stack --kind golang \
258
+ --repo-url https://github.com/joelwembo/va-sample-golang.git
259
+ ```
260
+
261
+ Default: deploys `traefik/whoami:latest` to inst3:8085 and polls until it
262
+ returns HTTP 200. See `python3 deploy_app.py --help` for flags.
263
+
264
+ ## Run the async demo
265
+
266
+ ```bash
267
+ pip install httpx
268
+ python3 deploy_async.py
269
+ ```
270
+
271
+ Drops three redis containers onto a single host **in parallel** via
272
+ `asyncio.gather()`. Verified live: 3 deploys in 22.8s wall clock vs.
273
+ ~57s sequential — a 2.5× speedup, and a 3× win at higher fan-out.
274
+
275
+ ```python
276
+ import asyncio, vxsdk_async as vx
277
+
278
+ async def main():
279
+ async with await vx.AsyncClient.load_from_vxcli() as c:
280
+ results = await asyncio.gather(
281
+ c.deploy.container(host=h1, ssh_user="ubuntu", key_pair_name=K, image="redis:7", ports=["6381:6379"], name="r1"),
282
+ c.deploy.container(host=h2, ssh_user="ubuntu", key_pair_name=K, image="redis:7", ports=["6381:6379"], name="r2"),
283
+ c.deploy.container(host=h3, ssh_user="ubuntu", key_pair_name=K, image="redis:7", ports=["6381:6379"], name="r3"),
284
+ )
285
+
286
+ asyncio.run(main())
287
+ ```
@@ -0,0 +1,6 @@
1
+ vxsdk.py,sha256=yilLgPuNa_ZKlM_4c5Lt7CZxR-p5LNO2wERXpPMzFHI,173181
2
+ vxsdk_async.py,sha256=T22EH3ZgmVp1DGto8P-AQlT3RXB06lfju5sFvPK49Ho,67226
3
+ vxsdk-0.1.0.dist-info/METADATA,sha256=V4a2oT-lGCSKt3QdQUvmI9prKg547rh1UztZYOMR9D4,11879
4
+ vxsdk-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
5
+ vxsdk-0.1.0.dist-info/top_level.txt,sha256=YrtNolpWp2PjA8nQAuFcpz54y74UglCTigafE_hWqhM,18
6
+ vxsdk-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ vxsdk
2
+ vxsdk_async