Initial commit: Vultr API v2 Python wrapper with FastAPI server

- vultr_api/: Python library wrapping Vultr API v2
  - 17 resource modules (instances, dns, firewall, vpc, etc.)
  - Pagination support, error handling

- server/: FastAPI REST server
  - All API endpoints exposed via HTTP
  - X-API-Key header authentication
  - Swagger docs at /docs

- Podman quadlet config for systemd deployment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
HWANG BYUNGHA
2026-01-22 01:08:17 +09:00
commit 184054c6c1
48 changed files with 6058 additions and 0 deletions

View File

@@ -0,0 +1,108 @@
"""
Snapshots Resource
Snapshot management
"""
from typing import Dict, List
from .base import BaseResource
class SnapshotsResource(BaseResource):
"""
Snapshot management
Usage:
# List snapshots
snapshots = client.snapshots.list()
# Create snapshot from instance
snapshot = client.snapshots.create(instance_id="instance-id", description="My snapshot")
# Create from URL
snapshot = client.snapshots.create_from_url(url="https://example.com/image.raw")
"""
def list(self, per_page: int = 100, cursor: str = None) -> Dict:
"""
List snapshots
Returns:
Dict with 'snapshots' list and 'meta' pagination
"""
params = {"per_page": per_page}
if cursor:
params["cursor"] = cursor
return self.client.get("snapshots", params=params)
def list_all(self) -> List[Dict]:
"""List all snapshots (auto-paginate)"""
return self.client.paginate("snapshots", "snapshots")
def get(self, snapshot_id: str) -> Dict:
"""
Get snapshot details
Args:
snapshot_id: Snapshot ID
Returns:
Snapshot details
"""
response = self.client.get(f"snapshots/{snapshot_id}")
return response.get("snapshot", {})
def create(self, instance_id: str, description: str = None) -> Dict:
"""
Create a snapshot from an instance
Args:
instance_id: Instance ID to snapshot
description: Snapshot description
Returns:
Created snapshot details
"""
data = {"instance_id": instance_id}
if description:
data["description"] = description
response = self.client.post("snapshots", data)
return response.get("snapshot", {})
def create_from_url(self, url: str, description: str = None) -> Dict:
"""
Create a snapshot from a URL
Args:
url: URL to raw disk image
description: Snapshot description
Returns:
Created snapshot details
"""
data = {"url": url}
if description:
data["description"] = description
response = self.client.post("snapshots/create-from-url", data)
return response.get("snapshot", {})
def update(self, snapshot_id: str, description: str) -> None:
"""
Update snapshot description
Args:
snapshot_id: Snapshot ID
description: New description
"""
self.client.put(f"snapshots/{snapshot_id}", {"description": description})
def delete(self, snapshot_id: str) -> None:
"""
Delete a snapshot
Args:
snapshot_id: Snapshot ID to delete
"""
self.client.delete(f"snapshots/{snapshot_id}")