Make API endpoints compatible with Vultr API v2 format
- Change auth from X-API-Key header to Authorization: Bearer format - Add /v2 prefix to all endpoints to match Vultr API URL structure - Fix router paths (dns, firewall) to avoid duplicate path segments - Split VPC 2.0 into separate router at /v2/vpc2 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ from . import (
|
||||
block_storage,
|
||||
reserved_ips,
|
||||
vpc,
|
||||
vpc2,
|
||||
load_balancers,
|
||||
bare_metal,
|
||||
backups,
|
||||
@@ -29,6 +30,7 @@ __all__ = [
|
||||
"block_storage",
|
||||
"reserved_ips",
|
||||
"vpc",
|
||||
"vpc2",
|
||||
"load_balancers",
|
||||
"bare_metal",
|
||||
"backups",
|
||||
|
||||
@@ -29,7 +29,7 @@ class UpdateRecordRequest(BaseModel):
|
||||
priority: Optional[int] = None
|
||||
|
||||
|
||||
@router.get("/domains")
|
||||
@router.get("")
|
||||
async def list_domains(
|
||||
per_page: int = Query(25, le=500),
|
||||
cursor: Optional[str] = None,
|
||||
@@ -39,44 +39,44 @@ async def list_domains(
|
||||
return client.dns.list_domains(per_page=per_page, cursor=cursor)
|
||||
|
||||
|
||||
@router.get("/domains/all")
|
||||
@router.get("/all")
|
||||
async def list_all_domains(client: VultrClient = Depends(get_client)):
|
||||
"""List all DNS domains (auto-paginated)"""
|
||||
return {"domains": client.dns.list_all_domains()}
|
||||
|
||||
|
||||
@router.get("/domains/{domain}")
|
||||
@router.get("/{domain}")
|
||||
async def get_domain(domain: str, client: VultrClient = Depends(get_client)):
|
||||
"""Get DNS domain details"""
|
||||
return client.dns.get_domain(domain)
|
||||
|
||||
|
||||
@router.post("/domains")
|
||||
@router.post("")
|
||||
async def create_domain(req: CreateDomainRequest, client: VultrClient = Depends(get_client)):
|
||||
"""Create a DNS domain"""
|
||||
return client.dns.create_domain(req.domain, ip=req.ip)
|
||||
|
||||
|
||||
@router.delete("/domains/{domain}")
|
||||
@router.delete("/{domain}")
|
||||
async def delete_domain(domain: str, client: VultrClient = Depends(get_client)):
|
||||
"""Delete a DNS domain"""
|
||||
return client.dns.delete_domain(domain)
|
||||
|
||||
|
||||
@router.get("/domains/{domain}/soa")
|
||||
@router.get("/{domain}/soa")
|
||||
async def get_soa(domain: str, client: VultrClient = Depends(get_client)):
|
||||
"""Get SOA record for a domain"""
|
||||
return client.dns.get_soa(domain)
|
||||
|
||||
|
||||
@router.get("/domains/{domain}/dnssec")
|
||||
@router.get("/{domain}/dnssec")
|
||||
async def get_dnssec(domain: str, client: VultrClient = Depends(get_client)):
|
||||
"""Get DNSSEC info for a domain"""
|
||||
return client.dns.get_dnssec(domain)
|
||||
|
||||
|
||||
# Records
|
||||
@router.get("/domains/{domain}/records")
|
||||
@router.get("/{domain}/records")
|
||||
async def list_records(
|
||||
domain: str,
|
||||
per_page: int = Query(25, le=500),
|
||||
@@ -87,19 +87,19 @@ async def list_records(
|
||||
return client.dns.list_records(domain, per_page=per_page, cursor=cursor)
|
||||
|
||||
|
||||
@router.get("/domains/{domain}/records/all")
|
||||
@router.get("/{domain}/records/all")
|
||||
async def list_all_records(domain: str, client: VultrClient = Depends(get_client)):
|
||||
"""List all DNS records (auto-paginated)"""
|
||||
return {"records": client.dns.list_all_records(domain)}
|
||||
|
||||
|
||||
@router.get("/domains/{domain}/records/{record_id}")
|
||||
@router.get("/{domain}/records/{record_id}")
|
||||
async def get_record(domain: str, record_id: str, client: VultrClient = Depends(get_client)):
|
||||
"""Get a DNS record"""
|
||||
return client.dns.get_record(domain, record_id)
|
||||
|
||||
|
||||
@router.post("/domains/{domain}/records")
|
||||
@router.post("/{domain}/records")
|
||||
async def create_record(domain: str, req: CreateRecordRequest, client: VultrClient = Depends(get_client)):
|
||||
"""Create a DNS record"""
|
||||
return client.dns.create_record(
|
||||
@@ -112,44 +112,44 @@ async def create_record(domain: str, req: CreateRecordRequest, client: VultrClie
|
||||
)
|
||||
|
||||
|
||||
@router.patch("/domains/{domain}/records/{record_id}")
|
||||
@router.patch("/{domain}/records/{record_id}")
|
||||
async def update_record(domain: str, record_id: str, req: UpdateRecordRequest, client: VultrClient = Depends(get_client)):
|
||||
"""Update a DNS record"""
|
||||
return client.dns.update_record(domain, record_id, **req.model_dump(exclude_none=True))
|
||||
|
||||
|
||||
@router.delete("/domains/{domain}/records/{record_id}")
|
||||
@router.delete("/{domain}/records/{record_id}")
|
||||
async def delete_record(domain: str, record_id: str, client: VultrClient = Depends(get_client)):
|
||||
"""Delete a DNS record"""
|
||||
return client.dns.delete_record(domain, record_id)
|
||||
|
||||
|
||||
# Convenience endpoints
|
||||
@router.post("/domains/{domain}/records/a")
|
||||
@router.post("/{domain}/records/a")
|
||||
async def create_a_record(domain: str, name: str, ip: str, ttl: int = 300, client: VultrClient = Depends(get_client)):
|
||||
"""Create an A record"""
|
||||
return client.dns.create_a_record(domain, name, ip, ttl)
|
||||
|
||||
|
||||
@router.post("/domains/{domain}/records/aaaa")
|
||||
@router.post("/{domain}/records/aaaa")
|
||||
async def create_aaaa_record(domain: str, name: str, ip: str, ttl: int = 300, client: VultrClient = Depends(get_client)):
|
||||
"""Create an AAAA record"""
|
||||
return client.dns.create_aaaa_record(domain, name, ip, ttl)
|
||||
|
||||
|
||||
@router.post("/domains/{domain}/records/cname")
|
||||
@router.post("/{domain}/records/cname")
|
||||
async def create_cname_record(domain: str, name: str, target: str, ttl: int = 300, client: VultrClient = Depends(get_client)):
|
||||
"""Create a CNAME record"""
|
||||
return client.dns.create_cname_record(domain, name, target, ttl)
|
||||
|
||||
|
||||
@router.post("/domains/{domain}/records/txt")
|
||||
@router.post("/{domain}/records/txt")
|
||||
async def create_txt_record(domain: str, name: str, data: str, ttl: int = 300, client: VultrClient = Depends(get_client)):
|
||||
"""Create a TXT record"""
|
||||
return client.dns.create_txt_record(domain, name, data, ttl)
|
||||
|
||||
|
||||
@router.post("/domains/{domain}/records/mx")
|
||||
@router.post("/{domain}/records/mx")
|
||||
async def create_mx_record(domain: str, name: str, data: str, priority: int = 10, ttl: int = 300, client: VultrClient = Depends(get_client)):
|
||||
"""Create an MX record"""
|
||||
return client.dns.create_mx_record(domain, name, data, priority, ttl)
|
||||
|
||||
@@ -23,7 +23,7 @@ class CreateRuleRequest(BaseModel):
|
||||
notes: Optional[str] = None
|
||||
|
||||
|
||||
@router.get("/groups")
|
||||
@router.get("")
|
||||
async def list_groups(
|
||||
per_page: int = Query(25, le=500),
|
||||
cursor: Optional[str] = None,
|
||||
@@ -33,38 +33,38 @@ async def list_groups(
|
||||
return client.firewall.list_groups(per_page=per_page, cursor=cursor)
|
||||
|
||||
|
||||
@router.get("/groups/all")
|
||||
@router.get("/all")
|
||||
async def list_all_groups(client: VultrClient = Depends(get_client)):
|
||||
"""List all firewall groups (auto-paginated)"""
|
||||
return {"firewall_groups": client.firewall.list_all_groups()}
|
||||
|
||||
|
||||
@router.get("/groups/{group_id}")
|
||||
@router.get("/{group_id}")
|
||||
async def get_group(group_id: str, client: VultrClient = Depends(get_client)):
|
||||
"""Get firewall group details"""
|
||||
return client.firewall.get_group(group_id)
|
||||
|
||||
|
||||
@router.post("/groups")
|
||||
@router.post("")
|
||||
async def create_group(req: CreateGroupRequest, client: VultrClient = Depends(get_client)):
|
||||
"""Create a firewall group"""
|
||||
return client.firewall.create_group(description=req.description)
|
||||
|
||||
|
||||
@router.patch("/groups/{group_id}")
|
||||
@router.patch("/{group_id}")
|
||||
async def update_group(group_id: str, description: str, client: VultrClient = Depends(get_client)):
|
||||
"""Update a firewall group"""
|
||||
return client.firewall.update_group(group_id, description=description)
|
||||
|
||||
|
||||
@router.delete("/groups/{group_id}")
|
||||
@router.delete("/{group_id}")
|
||||
async def delete_group(group_id: str, client: VultrClient = Depends(get_client)):
|
||||
"""Delete a firewall group"""
|
||||
return client.firewall.delete_group(group_id)
|
||||
|
||||
|
||||
# Rules
|
||||
@router.get("/groups/{group_id}/rules")
|
||||
@router.get("/{group_id}/rules")
|
||||
async def list_rules(
|
||||
group_id: str,
|
||||
per_page: int = Query(25, le=500),
|
||||
@@ -75,50 +75,50 @@ async def list_rules(
|
||||
return client.firewall.list_rules(group_id, per_page=per_page, cursor=cursor)
|
||||
|
||||
|
||||
@router.get("/groups/{group_id}/rules/all")
|
||||
@router.get("/{group_id}/rules/all")
|
||||
async def list_all_rules(group_id: str, client: VultrClient = Depends(get_client)):
|
||||
"""List all firewall rules (auto-paginated)"""
|
||||
return {"firewall_rules": client.firewall.list_all_rules(group_id)}
|
||||
|
||||
|
||||
@router.get("/groups/{group_id}/rules/{rule_id}")
|
||||
@router.get("/{group_id}/rules/{rule_id}")
|
||||
async def get_rule(group_id: str, rule_id: int, client: VultrClient = Depends(get_client)):
|
||||
"""Get a firewall rule"""
|
||||
return client.firewall.get_rule(group_id, rule_id)
|
||||
|
||||
|
||||
@router.post("/groups/{group_id}/rules")
|
||||
@router.post("/{group_id}/rules")
|
||||
async def create_rule(group_id: str, req: CreateRuleRequest, client: VultrClient = Depends(get_client)):
|
||||
"""Create a firewall rule"""
|
||||
return client.firewall.create_rule(group_id, **req.model_dump(exclude_none=True))
|
||||
|
||||
|
||||
@router.delete("/groups/{group_id}/rules/{rule_id}")
|
||||
@router.delete("/{group_id}/rules/{rule_id}")
|
||||
async def delete_rule(group_id: str, rule_id: int, client: VultrClient = Depends(get_client)):
|
||||
"""Delete a firewall rule"""
|
||||
return client.firewall.delete_rule(group_id, rule_id)
|
||||
|
||||
|
||||
# Convenience endpoints
|
||||
@router.post("/groups/{group_id}/rules/allow-ssh")
|
||||
@router.post("/{group_id}/rules/allow-ssh")
|
||||
async def allow_ssh(group_id: str, source: str = "0.0.0.0/0", client: VultrClient = Depends(get_client)):
|
||||
"""Allow SSH (port 22) from source"""
|
||||
return client.firewall.allow_ssh(group_id, source=source)
|
||||
|
||||
|
||||
@router.post("/groups/{group_id}/rules/allow-http")
|
||||
@router.post("/{group_id}/rules/allow-http")
|
||||
async def allow_http(group_id: str, source: str = "0.0.0.0/0", client: VultrClient = Depends(get_client)):
|
||||
"""Allow HTTP (port 80) from source"""
|
||||
return client.firewall.allow_http(group_id, source=source)
|
||||
|
||||
|
||||
@router.post("/groups/{group_id}/rules/allow-https")
|
||||
@router.post("/{group_id}/rules/allow-https")
|
||||
async def allow_https(group_id: str, source: str = "0.0.0.0/0", client: VultrClient = Depends(get_client)):
|
||||
"""Allow HTTPS (port 443) from source"""
|
||||
return client.firewall.allow_https(group_id, source=source)
|
||||
|
||||
|
||||
@router.post("/groups/{group_id}/rules/allow-ping")
|
||||
@router.post("/{group_id}/rules/allow-ping")
|
||||
async def allow_ping(group_id: str, source: str = "0.0.0.0/0", client: VultrClient = Depends(get_client)):
|
||||
"""Allow ICMP ping from source"""
|
||||
return client.firewall.allow_ping(group_id, source=source)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""VPC router"""
|
||||
"""VPC router (VPC 1.0)"""
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from typing import Optional, List
|
||||
from typing import Optional
|
||||
from pydantic import BaseModel
|
||||
|
||||
from vultr_api import VultrClient
|
||||
@@ -20,18 +20,6 @@ class UpdateVPCRequest(BaseModel):
|
||||
description: str
|
||||
|
||||
|
||||
class CreateVPC2Request(BaseModel):
|
||||
region: str
|
||||
description: Optional[str] = None
|
||||
ip_block: Optional[str] = None
|
||||
prefix_length: Optional[int] = None
|
||||
|
||||
|
||||
class AttachVPC2Request(BaseModel):
|
||||
nodes: List[dict] # [{"id": "instance_id", "ip_address": "10.0.0.1"}, ...]
|
||||
|
||||
|
||||
# VPC 1.0
|
||||
@router.get("")
|
||||
async def list_vpcs(
|
||||
per_page: int = Query(25, le=500),
|
||||
@@ -70,67 +58,3 @@ async def update_vpc(vpc_id: str, req: UpdateVPCRequest, client: VultrClient = D
|
||||
async def delete_vpc(vpc_id: str, client: VultrClient = Depends(get_client)):
|
||||
"""Delete a VPC"""
|
||||
return client.vpc.delete(vpc_id)
|
||||
|
||||
|
||||
# VPC 2.0
|
||||
@router.get("/v2/list")
|
||||
async def list_vpc2s(
|
||||
per_page: int = Query(25, le=500),
|
||||
cursor: Optional[str] = None,
|
||||
client: VultrClient = Depends(get_client)
|
||||
):
|
||||
"""List all VPC 2.0 networks"""
|
||||
return client.vpc.list_vpc2(per_page=per_page, cursor=cursor)
|
||||
|
||||
|
||||
@router.get("/v2/all")
|
||||
async def list_all_vpc2s(client: VultrClient = Depends(get_client)):
|
||||
"""List all VPC 2.0 networks (auto-paginated)"""
|
||||
return {"vpcs": client.vpc.list_all_vpc2()}
|
||||
|
||||
|
||||
@router.get("/v2/{vpc_id}")
|
||||
async def get_vpc2(vpc_id: str, client: VultrClient = Depends(get_client)):
|
||||
"""Get VPC 2.0 details"""
|
||||
return client.vpc.get_vpc2(vpc_id)
|
||||
|
||||
|
||||
@router.post("/v2")
|
||||
async def create_vpc2(req: CreateVPC2Request, client: VultrClient = Depends(get_client)):
|
||||
"""Create a VPC 2.0 network"""
|
||||
return client.vpc.create_vpc2(**req.model_dump(exclude_none=True))
|
||||
|
||||
|
||||
@router.patch("/v2/{vpc_id}")
|
||||
async def update_vpc2(vpc_id: str, description: str, client: VultrClient = Depends(get_client)):
|
||||
"""Update a VPC 2.0 network"""
|
||||
return client.vpc.update_vpc2(vpc_id, description=description)
|
||||
|
||||
|
||||
@router.delete("/v2/{vpc_id}")
|
||||
async def delete_vpc2(vpc_id: str, client: VultrClient = Depends(get_client)):
|
||||
"""Delete a VPC 2.0 network"""
|
||||
return client.vpc.delete_vpc2(vpc_id)
|
||||
|
||||
|
||||
@router.get("/v2/{vpc_id}/nodes")
|
||||
async def list_vpc2_nodes(
|
||||
vpc_id: str,
|
||||
per_page: int = Query(25, le=500),
|
||||
cursor: Optional[str] = None,
|
||||
client: VultrClient = Depends(get_client)
|
||||
):
|
||||
"""List nodes attached to a VPC 2.0"""
|
||||
return client.vpc.list_vpc2_nodes(vpc_id, per_page=per_page, cursor=cursor)
|
||||
|
||||
|
||||
@router.post("/v2/{vpc_id}/nodes/attach")
|
||||
async def attach_vpc2_nodes(vpc_id: str, req: AttachVPC2Request, client: VultrClient = Depends(get_client)):
|
||||
"""Attach nodes to a VPC 2.0"""
|
||||
return client.vpc.attach_vpc2_nodes(vpc_id, nodes=req.nodes)
|
||||
|
||||
|
||||
@router.post("/v2/{vpc_id}/nodes/detach")
|
||||
async def detach_vpc2_nodes(vpc_id: str, req: AttachVPC2Request, client: VultrClient = Depends(get_client)):
|
||||
"""Detach nodes from a VPC 2.0"""
|
||||
return client.vpc.detach_vpc2_nodes(vpc_id, nodes=req.nodes)
|
||||
|
||||
83
server/routers/vpc2.py
Normal file
83
server/routers/vpc2.py
Normal file
@@ -0,0 +1,83 @@
|
||||
"""VPC 2.0 router"""
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from typing import Optional, List
|
||||
from pydantic import BaseModel
|
||||
|
||||
from vultr_api import VultrClient
|
||||
from deps import get_client
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
|
||||
class CreateVPC2Request(BaseModel):
|
||||
region: str
|
||||
description: Optional[str] = None
|
||||
ip_block: Optional[str] = None
|
||||
prefix_length: Optional[int] = None
|
||||
|
||||
|
||||
class AttachVPC2Request(BaseModel):
|
||||
nodes: List[dict] # [{"id": "instance_id", "ip_address": "10.0.0.1"}, ...]
|
||||
|
||||
|
||||
@router.get("")
|
||||
async def list_vpc2s(
|
||||
per_page: int = Query(25, le=500),
|
||||
cursor: Optional[str] = None,
|
||||
client: VultrClient = Depends(get_client)
|
||||
):
|
||||
"""List all VPC 2.0 networks"""
|
||||
return client.vpc.list_vpc2(per_page=per_page, cursor=cursor)
|
||||
|
||||
|
||||
@router.get("/all")
|
||||
async def list_all_vpc2s(client: VultrClient = Depends(get_client)):
|
||||
"""List all VPC 2.0 networks (auto-paginated)"""
|
||||
return {"vpcs": client.vpc.list_all_vpc2()}
|
||||
|
||||
|
||||
@router.get("/{vpc_id}")
|
||||
async def get_vpc2(vpc_id: str, client: VultrClient = Depends(get_client)):
|
||||
"""Get VPC 2.0 details"""
|
||||
return client.vpc.get_vpc2(vpc_id)
|
||||
|
||||
|
||||
@router.post("")
|
||||
async def create_vpc2(req: CreateVPC2Request, client: VultrClient = Depends(get_client)):
|
||||
"""Create a VPC 2.0 network"""
|
||||
return client.vpc.create_vpc2(**req.model_dump(exclude_none=True))
|
||||
|
||||
|
||||
@router.patch("/{vpc_id}")
|
||||
async def update_vpc2(vpc_id: str, description: str, client: VultrClient = Depends(get_client)):
|
||||
"""Update a VPC 2.0 network"""
|
||||
return client.vpc.update_vpc2(vpc_id, description=description)
|
||||
|
||||
|
||||
@router.delete("/{vpc_id}")
|
||||
async def delete_vpc2(vpc_id: str, client: VultrClient = Depends(get_client)):
|
||||
"""Delete a VPC 2.0 network"""
|
||||
return client.vpc.delete_vpc2(vpc_id)
|
||||
|
||||
|
||||
@router.get("/{vpc_id}/nodes")
|
||||
async def list_vpc2_nodes(
|
||||
vpc_id: str,
|
||||
per_page: int = Query(25, le=500),
|
||||
cursor: Optional[str] = None,
|
||||
client: VultrClient = Depends(get_client)
|
||||
):
|
||||
"""List nodes attached to a VPC 2.0"""
|
||||
return client.vpc.list_vpc2_nodes(vpc_id, per_page=per_page, cursor=cursor)
|
||||
|
||||
|
||||
@router.post("/{vpc_id}/nodes/attach")
|
||||
async def attach_vpc2_nodes(vpc_id: str, req: AttachVPC2Request, client: VultrClient = Depends(get_client)):
|
||||
"""Attach nodes to a VPC 2.0"""
|
||||
return client.vpc.attach_vpc2_nodes(vpc_id, nodes=req.nodes)
|
||||
|
||||
|
||||
@router.post("/{vpc_id}/nodes/detach")
|
||||
async def detach_vpc2_nodes(vpc_id: str, req: AttachVPC2Request, client: VultrClient = Depends(get_client)):
|
||||
"""Detach nodes from a VPC 2.0"""
|
||||
return client.vpc.detach_vpc2_nodes(vpc_id, nodes=req.nodes)
|
||||
Reference in New Issue
Block a user