- 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>
87 lines
2.7 KiB
Python
87 lines
2.7 KiB
Python
"""Reserved IPs 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 CreateReservedIPRequest(BaseModel):
|
|
region: str
|
|
ip_type: str = "v4" # v4 or v6
|
|
label: Optional[str] = None
|
|
|
|
|
|
class UpdateReservedIPRequest(BaseModel):
|
|
label: str
|
|
|
|
|
|
class AttachReservedIPRequest(BaseModel):
|
|
instance_id: str
|
|
|
|
|
|
class ConvertReservedIPRequest(BaseModel):
|
|
ip_address: str
|
|
label: Optional[str] = None
|
|
|
|
|
|
@router.get("")
|
|
async def list_reserved_ips(
|
|
per_page: int = Query(25, le=500),
|
|
cursor: Optional[str] = None,
|
|
client: VultrClient = Depends(get_client)
|
|
):
|
|
"""List all reserved IPs"""
|
|
return client.reserved_ips.list(per_page=per_page, cursor=cursor)
|
|
|
|
|
|
@router.get("/all")
|
|
async def list_all_reserved_ips(client: VultrClient = Depends(get_client)):
|
|
"""List all reserved IPs (auto-paginated)"""
|
|
return {"reserved_ips": client.reserved_ips.list_all()}
|
|
|
|
|
|
@router.get("/{reserved_ip}")
|
|
async def get_reserved_ip(reserved_ip: str, client: VultrClient = Depends(get_client)):
|
|
"""Get reserved IP details"""
|
|
return client.reserved_ips.get(reserved_ip)
|
|
|
|
|
|
@router.post("")
|
|
async def create_reserved_ip(req: CreateReservedIPRequest, client: VultrClient = Depends(get_client)):
|
|
"""Create a reserved IP"""
|
|
return client.reserved_ips.create(**req.model_dump(exclude_none=True))
|
|
|
|
|
|
@router.patch("/{reserved_ip}")
|
|
async def update_reserved_ip(reserved_ip: str, req: UpdateReservedIPRequest, client: VultrClient = Depends(get_client)):
|
|
"""Update a reserved IP"""
|
|
return client.reserved_ips.update(reserved_ip, label=req.label)
|
|
|
|
|
|
@router.delete("/{reserved_ip}")
|
|
async def delete_reserved_ip(reserved_ip: str, client: VultrClient = Depends(get_client)):
|
|
"""Delete a reserved IP"""
|
|
return client.reserved_ips.delete(reserved_ip)
|
|
|
|
|
|
@router.post("/{reserved_ip}/attach")
|
|
async def attach_reserved_ip(reserved_ip: str, req: AttachReservedIPRequest, client: VultrClient = Depends(get_client)):
|
|
"""Attach reserved IP to an instance"""
|
|
return client.reserved_ips.attach(reserved_ip, instance_id=req.instance_id)
|
|
|
|
|
|
@router.post("/{reserved_ip}/detach")
|
|
async def detach_reserved_ip(reserved_ip: str, client: VultrClient = Depends(get_client)):
|
|
"""Detach reserved IP from an instance"""
|
|
return client.reserved_ips.detach(reserved_ip)
|
|
|
|
|
|
@router.post("/convert")
|
|
async def convert_to_reserved_ip(req: ConvertReservedIPRequest, client: VultrClient = Depends(get_client)):
|
|
"""Convert an instance IP to a reserved IP"""
|
|
return client.reserved_ips.convert(ip_address=req.ip_address, label=req.label)
|