348 lines
8.9 KiB
Plaintext
348 lines
8.9 KiB
Plaintext
# 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
|
|
}
|
|
|
|
let headers = [Authorization $"Bearer ($token)"]
|
|
|
|
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)"}
|
|
}
|
|
}
|
|
} | complete)
|
|
if $result.exit_code != 0 {
|
|
error make {msg: $"Hetzner API request failed: ($result.stderr)"}
|
|
} else {
|
|
$result.stdout
|
|
}
|
|
}
|
|
|
|
# List all servers
|
|
export def hetzner_api_list_servers []: nothing -> list {
|
|
let response = (hetzner_api_request "GET" "/servers")
|
|
|
|
if ($response | describe) =~ "error" {
|
|
error make {msg: "Failed to list servers from API"}
|
|
}
|
|
|
|
if ($response | has servers) {
|
|
$response.servers
|
|
} else {
|
|
[]
|
|
}
|
|
}
|
|
|
|
# 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)")
|
|
|
|
if ($response | describe) =~ "error" {
|
|
error make {msg: $"Server not found: ($id_or_name)"}
|
|
}
|
|
|
|
if ($response | has server) {
|
|
$response.server
|
|
} else {
|
|
$response
|
|
}
|
|
}
|
|
|
|
# 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
|
|
}
|
|
}
|
|
|
|
# Delete a server
|
|
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)
|
|
|
|
if ($response | has action) {
|
|
$response.action
|
|
} else {
|
|
$response
|
|
}
|
|
}
|
|
|
|
# List all locations
|
|
export def hetzner_api_list_locations []: nothing -> list {
|
|
let response = (hetzner_api_request "GET" "/locations")
|
|
|
|
if ($response | has locations) {
|
|
$response.locations
|
|
} else {
|
|
[]
|
|
}
|
|
}
|
|
|
|
# List all server types
|
|
export def hetzner_api_list_server_types []: nothing -> list {
|
|
let response = (hetzner_api_request "GET" "/server_types")
|
|
|
|
if ($response | has server_types) {
|
|
$response.server_types
|
|
} else {
|
|
[]
|
|
}
|
|
}
|
|
|
|
# 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)")
|
|
|
|
if ($response | has server_type) {
|
|
$response.server_type
|
|
} else {
|
|
$response
|
|
}
|
|
}
|
|
|
|
# List all images
|
|
export def hetzner_api_list_images []: nothing -> list {
|
|
let response = (hetzner_api_request "GET" "/images")
|
|
|
|
if ($response | has images) {
|
|
$response.images
|
|
} else {
|
|
[]
|
|
}
|
|
}
|
|
|
|
# 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 {
|
|
[]
|
|
}
|
|
}
|
|
|
|
# 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
|
|
}
|
|
}
|
|
|
|
# Delete a volume
|
|
export def hetzner_api_delete_volume [id: string]: nothing -> nothing {
|
|
hetzner_api_request "DELETE" $"/volumes/($id)"
|
|
null
|
|
}
|
|
|
|
# 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)
|
|
|
|
if ($response | has action) {
|
|
$response.action
|
|
} else {
|
|
$response
|
|
}
|
|
}
|
|
|
|
# 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
|
|
}
|
|
}
|
|
|
|
# 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 {
|
|
[]
|
|
}
|
|
}
|
|
|
|
# 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)")
|
|
|
|
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)}
|
|
}
|
|
|
|
let response = (hetzner_api_request "POST" $"/servers/($server_id)/actions/attach_to_network" $data)
|
|
|
|
if ($response | has action) {
|
|
$response.action
|
|
} else {
|
|
$response
|
|
}
|
|
}
|
|
|
|
# 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
|
|
} else {
|
|
$response
|
|
}
|
|
}
|
|
|
|
# List all floating IPs
|
|
export def hetzner_api_list_floating_ips []: nothing -> list {
|
|
let response = (hetzner_api_request "GET" "/floating_ips")
|
|
|
|
if ($response | has floating_ips) {
|
|
$response.floating_ips
|
|
} else {
|
|
[]
|
|
}
|
|
}
|
|
|
|
# Get pricing information
|
|
export def hetzner_api_get_pricing []: nothing -> record {
|
|
let response = (hetzner_api_request "GET" "/pricing")
|
|
|
|
if ($response | has pricing) {
|
|
$response.pricing
|
|
} else {
|
|
$response
|
|
}
|
|
}
|
|
|
|
# List SSH keys
|
|
export def hetzner_api_list_ssh_keys []: nothing -> list {
|
|
let response = (hetzner_api_request "GET" "/ssh_keys")
|
|
|
|
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
|
|
}
|
|
}
|
|
|
|
# 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
|
|
}
|
|
}
|