This commit is contained in:
anhduy-tech
2026-04-07 10:33:58 +07:00
parent dfc7914d3d
commit 52977d0104
6 changed files with 75 additions and 2 deletions

Binary file not shown.

View File

@@ -14,7 +14,7 @@ Including another URLconf
2. Add a URL to urlpatterns: re_path('blog/', include('blog.urls'))
"""
from django.urls import re_path
from app import views, cob, email, backup, server, importdata
from app import views,hetzner, cob, email, backup, server, importdata
urlpatterns = [
@@ -46,9 +46,11 @@ urlpatterns = [
re_path('set-token-expiry/', views.set_token_expiry),
re_path('download-contract/(?P<name>.+)', views.download_contract),
re_path('execute-command/$', server.execute_command),
re_path('hetzner/(?P<action>[\w]+)/$', hetzner.do_hetzner),
re_path('generate-document/$',views.generate_document),
re_path('model-fields/(?P<name>.+)/', importdata.model_fields),
re_path('read-excel/', importdata.read_excel),
re_path('find-key/$', importdata.find_key),
re_path('email-preview/$', views.preview_email_template)
]

69
app/hetzner.py Normal file
View File

@@ -0,0 +1,69 @@
# hetzner.py
from __future__ import annotations
import json
from os import environ
from dotenv import load_dotenv
from hcloud import Client
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
load_dotenv()
def get_client():
return Client(token=environ["HCLOUD_TOKEN"])
# ── router ──────────────────────────────────────────────────────────────────
@csrf_exempt
def do_hetzner(request, action):
routes = {
"get_server_types": get_server_types,
}
handler = routes.get(action)
if handler is None:
return JsonResponse({"error": f"Action '{action}' not found"}, status=404)
try:
body = json.loads(request.body) if request.body else {}
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON body"}, status=400)
return handler(request, body)
# ── handlers ─────────────────────────────────────────────────────────────────
def get_server_types(request, body):
client = get_client()
server_types = client.server_types.get_all()
def serialize_server_type(st):
dm = st.data_model
return {
"id": dm.id,
"name": dm.name,
"description": dm.description,
"category": dm.category,
"cores": dm.cores,
"memory": dm.memory,
"disk": dm.disk,
"storage_type": dm.storage_type,
"cpu_type": dm.cpu_type,
"architecture": dm.architecture,
"deprecated": dm.deprecated,
"prices": dm.prices,
"locations": [
{
"id": loc.location.id,
"name": loc.location.name,
"deprecation": {
"announced": loc.deprecation.announced.isoformat(),
"unavailable_after": loc.deprecation.unavailable_after.isoformat(),
} if loc.deprecation else None,
}
for loc in dm.locations
],
}
result = [serialize_server_type(st) for st in server_types]
return JsonResponse(result, safe=False)

View File

@@ -23,3 +23,5 @@ channels
prefect
croniter
uvicorn[standard]
hcloud
python-dotenv