feat: migrate api wrapper to rest v2 - #584
Conversation
deanq
left a comment
There was a problem hiding this comment.
A few correctness issues from the GraphQL to REST v2 migration, plus a couple of smaller notes. The silent behavior changes in create_endpoint and the KeyError in create_pod are the ones I'd want addressed before merge.
There was a problem hiding this comment.
馃煛 Changes recommended
Unresolved critical GraphQL input handling and moderate REST/CLI behavior issues block approval.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
This pull request migrates API helpers to REST API v2 while preserving the public interface and retaining GraphQL for profile reads and registry updates.
Changes:
- Adds REST transport and REST-backed resource operations.
- Updates CLI behavior, errors, tests, examples, and documentation.
- Removes obsolete GraphQL query and mutation builders.
File summaries
| File | Reviewed change |
|---|---|
tests/test_error.py |
Tests REST error metadata. |
tests/test_cli/test_cli_utils/test_info.py |
Updates REST SSH fixtures. |
tests/test_cli/test_cli_groups/test_project_functions.py |
Updates pod status fixtures. |
tests/test_cli/test_cli_groups/test_pod_commands.py |
Updates REST pod fields. |
tests/test_api/test_rest.py |
Adds REST transport tests. |
tests/test_api/test_mutations_templates.py |
Removes obsolete mutation tests. |
tests/test_api/test_mutations_pods.py |
Removes obsolete mutation tests. |
tests/test_api/test_mutation_endpoints.py |
Removes obsolete mutation tests. |
tests/test_api/test_mutation_container_registry_auth.py |
Tests the retained registry mutation. |
tests/test_api/test_ctl_commands.py |
Tests REST-backed commands. |
runpod/error.py |
Adds HTTP error details. |
runpod/cli/utils/rp_info.py |
Handles REST SSH data. |
runpod/cli/groups/project/functions.py |
Uses REST pod status; Moderate (1 vote): handle missing pods during 404 polling. |
runpod/cli/groups/pod/commands.py |
Displays REST pod fields. |
runpod/api/rest.py |
Implements authenticated REST transport. |
runpod/api/queries/pods.py |
Removes obsolete pod queries. |
runpod/api/queries/gpus.py |
Removes obsolete GPU queries. |
runpod/api/queries/endpoints.py |
Removes obsolete endpoint queries. |
runpod/api/mutations/user.py |
Removes obsolete user mutation. |
runpod/api/mutations/templates.py |
Removes obsolete template mutation. |
runpod/api/mutations/pods.py |
Removes obsolete pod mutations. |
runpod/api/mutations/endpoints.py |
Removes obsolete endpoint mutations. |
runpod/api/mutations/container_register_auth.py |
Retains registry updates; Critical (1 vote): escape or parameterize interpolated GraphQL values. |
runpod/api/ctl_commands.py |
Routes helpers through REST; Moderate (2 votes): validate complete instance IDs; Moderate (1 vote): support CPU volume overrides and missing mounts; Moderate (1 vote): preserve or reject unsupported resume_pod GPU counts. |
runpod/api/__init__.py |
Updates API package documentation. |
README.md |
Documents REST wrapper usage. |
examples/rest_wrapper.py |
Updates REST usage examples. |
docs/api/queries.md |
Documents REST response shapes; Nit (2 votes): show get_gpus() output as a list. |
docs/api/handling_errors.md |
Documents REST error handling. |
Review details
Suppressed comments (3)
runpod/api/ctl_commands.py:197
volume_mount_pathis a public option for both GPU and CPU pods, but this branch only runs whengpu_type_idis set. A CPU pod created from a template with a persistent volume therefore cannot override the inherited path (the previous mutation applied the mount path regardless of GPU/CPU), and a template withoutmountsalso raisesKeyErrorwhen an override is requested. Remove the GPU-only guard and treat missing mounts as an empty mapping.
elif template_id and gpu_type_id and volume_mount_path is not None:
template = run_rest_request(
"GET", f"/v2/templates/{_path_segment(template_id)}"
)
persistent = template["mounts"].get("persistent")
runpod/api/ctl_commands.py:230
gpu_countis part of the publicresume_podcontract, but this line discards it and the REST request always performs an unchanged start. Callers that previously requested a different GPU count now silently get different behavior; pass the count using the REST v2-supported action field, or reject/document the unsupported operation instead of ignoring the argument.
def resume_pod(pod_id: str, gpu_count: int) -> dict:
"""Start a stopped pod."""
_ = gpu_count
return run_rest_request(
runpod/cli/groups/project/functions.py:64
get_podnow returnsNonefor a 404, so a pod that disappears or is temporarily not visible during this polling loop makes the next iteration dereferenceNonewith.getand fail withAttributeError. Handle the missing pod explicitly before continuing to poll.
while new_pod.get("status") != "RUNNING" or new_pod.get("runtime") is None:
new_pod = get_pod(new_pod["id"])
- Files reviewed: 29/29 changed files
- Comments generated: 3
- Review effort level: Lite
馃挕 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Routes the existing API helpers through REST API v2 while preserving the public function surface and list unwrapping behavior. GraphQL is scoped to account profile reads and registry credential updates, since those operations are not exposed by REST API v2.
Linear: CON-1154