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,59 @@
"""Snapshots router"""
from fastapi import APIRouter, Depends, Query
from typing import Optional
from pydantic import BaseModel
from vultr_api import VultrClient
from deps import get_client
router = APIRouter()
class CreateSnapshotRequest(BaseModel):
instance_id: str
description: Optional[str] = None
class CreateSnapshotFromURLRequest(BaseModel):
url: str
description: Optional[str] = None
@router.get("")
async def list_snapshots(
per_page: int = Query(25, le=500),
cursor: Optional[str] = None,
client: VultrClient = Depends(get_client)
):
"""List all snapshots"""
return client.snapshots.list(per_page=per_page, cursor=cursor)
@router.get("/all")
async def list_all_snapshots(client: VultrClient = Depends(get_client)):
"""List all snapshots (auto-paginated)"""
return {"snapshots": client.snapshots.list_all()}
@router.get("/{snapshot_id}")
async def get_snapshot(snapshot_id: str, client: VultrClient = Depends(get_client)):
"""Get snapshot details"""
return client.snapshots.get(snapshot_id)
@router.post("")
async def create_snapshot(req: CreateSnapshotRequest, client: VultrClient = Depends(get_client)):
"""Create a snapshot from an instance"""
return client.snapshots.create(instance_id=req.instance_id, description=req.description)
@router.post("/from-url")
async def create_snapshot_from_url(req: CreateSnapshotFromURLRequest, client: VultrClient = Depends(get_client)):
"""Create a snapshot from a URL"""
return client.snapshots.create_from_url(url=req.url, description=req.description)
@router.delete("/{snapshot_id}")
async def delete_snapshot(snapshot_id: str, client: VultrClient = Depends(get_client)):
"""Delete a snapshot"""
return client.snapshots.delete(snapshot_id)