348 lines
8.9 KiB
Plaintext
Raw Permalink Normal View History

# Hetzner Cloud HTTP API Client
use env.nu *
# Get Bearer token for API authentication
export def hetzner_api_auth []: nothing -> string {
let token = (hetzner_api_token)
if ($token | is-empty) {
error make {msg: "HCLOUD_TOKEN environment variable not set. Set your Hetzner API token before using the API interface."}
}
$token
}
# Build full API URL
export def hetzner_api_url [path: string]: nothing -> string {
let base = (hetzner_api_url_base)
$"($base)($path)"
}
# Generic HTTP request with error handling
export def hetzner_api_request [method: string, path: string, data?: any]: nothing -> any {
let token = (hetzner_api_auth)
let url = (hetzner_api_url $path)
if (hetzner_debug) {
print $"DEBUG: hetzner_api_request method=($method) path=($path) url=($url)" | encode utf8 | into string
}
2025-10-07 10:32:04 +01:00
let headers = [Authorization $"Bearer ($token)"]
2025-10-07 10:32:04 +01:00
let result = (do {
match $method {
"GET" => {
http get --headers $headers --allow-errors $url
}
"POST" => {
http post --headers $headers --content-type application/json --allow-errors $url $data
}
"PUT" => {
http put --headers $headers --content-type application/json --allow-errors $url $data
}
"DELETE" => {
http delete --headers $headers --allow-errors $url
}
_ => {
error make {msg: $"Unsupported HTTP method: ($method)"}
2025-10-07 10:32:04 +01:00
}
}
} | complete)
if $result.exit_code != 0 {
error make {msg: $"Hetzner API request failed: ($result.stderr)"}
} else {
$result.stdout
}
}
2025-10-07 10:32:04 +01:00
# List all servers
export def hetzner_api_list_servers []: nothing -> list {
let response = (hetzner_api_request "GET" "/servers")
2025-10-07 10:32:04 +01:00
if ($response | describe) =~ "error" {
error make {msg: "Failed to list servers from API"}
}
2025-10-07 10:32:04 +01:00
if ($response | has servers) {
$response.servers
} else {
[]
}
}
2025-10-07 10:32:04 +01:00
# Get server info by ID or name
export def hetzner_api_server_info [id_or_name: string]: nothing -> record {
let response = (hetzner_api_request "GET" $"/servers/($id_or_name)")
2025-10-07 10:32:04 +01:00
if ($response | describe) =~ "error" {
error make {msg: $"Server not found: ($id_or_name)"}
}
2025-10-07 10:32:04 +01:00
if ($response | has server) {
$response.server
} else {
$response
}
}
2025-10-07 10:32:04 +01:00
# Create a new server
export def hetzner_api_create_server [config: record]: nothing -> record {
if (hetzner_debug) {
print $"DEBUG: Creating server with config: ($config | to json)" | encode utf8 | into string
}
let response = (hetzner_api_request "POST" "/servers" $config)
if ($response | describe) =~ "error" {
error make {msg: $"Failed to create server: ($response)"}
}
if ($response | has server) {
$response.server
} else {
$response
2025-10-07 10:32:04 +01:00
}
}
# Delete a server
2026-01-17 03:57:20 +00:00
export def hetzner_api_delete_server [id: string]: nothing -> nothing {
let response = (hetzner_api_request "DELETE" $"/servers/($id)")
null
}
# Perform server action (start, stop, reboot, etc.)
export def hetzner_api_server_action [id: string, action: string]: nothing -> record {
let data = {action: $action}
let response = (hetzner_api_request "POST" $"/servers/($id)/actions/($action)" $data)
2025-10-07 10:32:04 +01:00
if ($response | has action) {
$response.action
} else {
$response
2025-10-07 10:32:04 +01:00
}
}
# List all locations
export def hetzner_api_list_locations []: nothing -> list {
let response = (hetzner_api_request "GET" "/locations")
2025-10-07 10:32:04 +01:00
if ($response | has locations) {
$response.locations
} else {
[]
2025-10-07 10:32:04 +01:00
}
}
2025-10-07 10:32:04 +01:00
# List all server types
export def hetzner_api_list_server_types []: nothing -> list {
let response = (hetzner_api_request "GET" "/server_types")
2025-10-07 10:32:04 +01:00
if ($response | has server_types) {
$response.server_types
} else {
[]
2025-10-07 10:32:04 +01:00
}
}
# Get server type info
export def hetzner_api_server_type_info [id_or_name: string]: nothing -> record {
let response = (hetzner_api_request "GET" $"/server_types/($id_or_name)")
2025-10-07 10:32:04 +01:00
if ($response | has server_type) {
$response.server_type
} else {
$response
2025-10-07 10:32:04 +01:00
}
}
# List all images
export def hetzner_api_list_images []: nothing -> list {
let response = (hetzner_api_request "GET" "/images")
2025-10-07 10:32:04 +01:00
if ($response | has images) {
$response.images
} else {
[]
2025-10-07 10:32:04 +01:00
}
}
2025-10-07 10:32:04 +01:00
# List all volumes
export def hetzner_api_list_volumes []: nothing -> list {
let response = (hetzner_api_request "GET" "/volumes")
if ($response | has volumes) {
$response.volumes
} else {
[]
2025-10-07 10:32:04 +01:00
}
}
2025-10-07 10:32:04 +01:00
# Create a volume
export def hetzner_api_create_volume [config: record]: nothing -> record {
let response = (hetzner_api_request "POST" "/volumes" $config)
if ($response | has volume) {
$response.volume
} else {
$response
}
2025-10-07 10:32:04 +01:00
}
# Delete a volume
2026-01-17 03:57:20 +00:00
export def hetzner_api_delete_volume [id: string]: nothing -> nothing {
hetzner_api_request "DELETE" $"/volumes/($id)"
null
}
2025-10-07 10:32:04 +01:00
# Attach volume to server
export def hetzner_api_attach_volume [volume_id: string, server_id: string]: nothing -> record {
let data = {
server: ($server_id | into int)
automount: false
}
let response = (hetzner_api_request "POST" $"/volumes/($volume_id)/actions/attach" $data)
2025-10-07 10:32:04 +01:00
if ($response | has action) {
$response.action
} else {
$response
2025-10-07 10:32:04 +01:00
}
}
# Detach volume from server
export def hetzner_api_detach_volume [volume_id: string]: nothing -> record {
let response = (hetzner_api_request "POST" $"/volumes/($volume_id)/actions/detach" {})
if ($response | has action) {
$response.action
} else {
$response
2025-10-07 10:32:04 +01:00
}
}
# List all networks
export def hetzner_api_list_networks []: nothing -> list {
let response = (hetzner_api_request "GET" "/networks")
if ($response | has networks) {
$response.networks
} else {
[]
2025-10-07 10:32:04 +01:00
}
}
2025-10-07 10:32:04 +01:00
# Get network info
export def hetzner_api_network_info [id_or_name: string]: nothing -> record {
let response = (hetzner_api_request "GET" $"/networks/($id_or_name)")
2025-10-07 10:32:04 +01:00
if ($response | has network) {
$response.network
} else {
$response
}
}
# Attach network to server
export def hetzner_api_attach_network [server_id: string, network_id: string, ip?: string]: nothing -> record {
let data = if ($ip != null) {
{server: ($server_id | into int), network: ($network_id | into int), ip: $ip}
} else {
{server: ($server_id | into int), network: ($network_id | into int)}
}
2025-10-07 10:32:04 +01:00
let response = (hetzner_api_request "POST" $"/servers/($server_id)/actions/attach_to_network" $data)
2025-10-07 10:32:04 +01:00
if ($response | has action) {
$response.action
2025-10-07 10:32:04 +01:00
} else {
$response
2025-10-07 10:32:04 +01:00
}
}
# Detach network from server
export def hetzner_api_detach_network [server_id: string, network_id: string]: nothing -> record {
let data = {network: ($network_id | into int)}
let response = (hetzner_api_request "POST" $"/servers/($server_id)/actions/detach_from_network" $data)
if ($response | has action) {
$response.action
2025-10-07 10:32:04 +01:00
} else {
$response
}
}
2025-10-07 10:32:04 +01:00
# List all floating IPs
export def hetzner_api_list_floating_ips []: nothing -> list {
let response = (hetzner_api_request "GET" "/floating_ips")
2025-10-07 10:32:04 +01:00
if ($response | has floating_ips) {
$response.floating_ips
} else {
[]
2025-10-07 10:32:04 +01:00
}
}
# Get pricing information
export def hetzner_api_get_pricing []: nothing -> record {
let response = (hetzner_api_request "GET" "/pricing")
2025-10-07 10:32:04 +01:00
if ($response | has pricing) {
$response.pricing
} else {
$response
}
}
2025-10-07 10:32:04 +01:00
# List SSH keys
export def hetzner_api_list_ssh_keys []: nothing -> list {
let response = (hetzner_api_request "GET" "/ssh_keys")
2025-10-07 10:32:04 +01:00
if ($response | has ssh_keys) {
$response.ssh_keys
} else {
[]
}
}
# Get SSH key info
export def hetzner_api_ssh_key_info [id_or_name: string]: nothing -> record {
let response = (hetzner_api_request "GET" $"/ssh_keys/($id_or_name)")
if ($response | has ssh_key) {
$response.ssh_key
} else {
$response
2025-10-07 10:32:04 +01:00
}
}
# List firewalls
export def hetzner_api_list_firewalls []: nothing -> list {
let response = (hetzner_api_request "GET" "/firewalls")
if ($response | has firewalls) {
$response.firewalls
} else {
[]
}
}
# Get firewall info
export def hetzner_api_firewall_info [id_or_name: string]: nothing -> record {
let response = (hetzner_api_request "GET" $"/firewalls/($id_or_name)")
if ($response | has firewall) {
$response.firewall
} else {
$response
}
}
# Create firewall
export def hetzner_api_create_firewall [config: record]: nothing -> record {
let response = (hetzner_api_request "POST" "/firewalls" $config)
if ($response | has firewall) {
$response.firewall
} else {
$response
}
}