# CoreDNS API Client # Client for orchestrator DNS API endpoints # ../utils/log.nu does not exist — dangling import removed (ADR-025 L2). use domain/config/loader.nu [get-config] # Call orchestrator DNS API export def call-dns-api [ endpoint: string # API endpoint path (e.g., "/dns/record") method: string = "GET" # HTTP method body?: record # Request body --timeout: int = 30 # Request timeout in seconds ] -> record { log debug $"Calling DNS API: ($method) ($endpoint)" let config = get-config let coredns_config = $config.coredns? | default {} let api_endpoint = $coredns_config.dynamic_updates?.api_endpoint? | default "http://localhost:8080/dns" let full_url = $"($api_endpoint)($endpoint)" let result = (do { match $method { "GET" => { http get -t $timeout $full_url } "POST" => { if $body != null { http post -t $timeout -c "application/json" $full_url ($body | to json) } else { http post -t $timeout $full_url } } "PUT" => { if $body != null { http put -t $timeout -c "application/json" $full_url ($body | to json) } else { http put -t $timeout $full_url } } "DELETE" => { http delete -t $timeout $full_url } _ => { log error $"Unsupported HTTP method: [$method]" error make {msg: "Unsupported method"} } } } | complete) if $result.exit_code == 0 { { success: true response: $result.stdout } } else { log error $"DNS API call failed: [$result.stderr]" { success: false error: $result.stderr } } } # Add DNS record via API export def api-add-record [ hostname: string # Hostname ip_address: string # IP address record_type: string = "A" # Record type --zone: string = "provisioning.local" --ttl: int = 300 --comment: string = "" --check ] -> bool { log info $"Adding DNS record via API: ($hostname) -> ($ip_address)" if $check { log info "Check mode: Would add DNS record via API" return true } let body = { zone: $zone hostname: $hostname record_type: $record_type value: $ip_address ttl: $ttl comment: $comment } let result = call-dns-api "/record" "POST" $body if $result.success { log info $"DNS record added via API: ($hostname)" true } else { log error $"Failed to add DNS record via API: ($result.error)" false } } # Remove DNS record via API export def api-remove-record [ hostname: string # Hostname --zone: string = "provisioning.local" --check ] -> bool { log info $"Removing DNS record via API: ($hostname)" if $check { log info "Check mode: Would remove DNS record via API" return true } let body = { zone: $zone hostname: $hostname } let result = call-dns-api "/record" "DELETE" $body if $result.success { log info $"DNS record removed via API: ($hostname)" true } else { log error $"Failed to remove DNS record via API: ($result.error)" false } } # Update DNS record via API export def api-update-record [ hostname: string # Hostname ip_address: string # New IP address record_type: string = "A" # Record type --zone: string = "provisioning.local" --ttl: int = 300 --comment: string = "" --check ] -> bool { log info $"Updating DNS record via API: ($hostname) -> ($ip_address)" if $check { log info "Check mode: Would update DNS record via API" return true } let body = { zone: $zone hostname: $hostname record_type: $record_type value: $ip_address ttl: $ttl comment: $comment } let result = call-dns-api "/record" "PUT" $body if $result.success { log info $"DNS record updated via API: ($hostname)" true } else { log error $"Failed to update DNS record via API: ($result.error)" false } } # List DNS records via API export def api-list-records [ --zone: string = "provisioning.local" --format: string = "table" ] -> any { log debug $"Listing DNS records via API for zone: ($zone)" let result = call-dns-api $"/records?zone=($zone)" "GET" if $result.success { let records = $result.response match $format { "json" => { $records | to json } "yaml" => { $records | to yaml } _ => { $records } } } else { log error $"Failed to list DNS records via API: ($result.error)" [] } } # Get DNS zones via API export def api-list-zones [] -> list { log debug "Listing DNS zones via API" let result = call-dns-api "/zones" "GET" if $result.success { $result.response } else { log error $"Failed to list DNS zones via API: ($result.error)" [] } } # Reload CoreDNS via API export def api-reload-coredns [] -> bool { log info "Reloading CoreDNS via API" let result = call-dns-api "/reload" "POST" if $result.success { log info "CoreDNS reloaded via API" true } else { log error $"Failed to reload CoreDNS via API: ($result.error)" false } } # Check DNS health via API export def api-check-health [] -> record { log debug "Checking DNS health via API" let result = call-dns-api "/health" "GET" if $result.success { $result.response } else { log error $"Failed to check DNS health via API: ($result.error)" { healthy: false error: $result.error } } } # Batch add DNS records via API export def api-batch-add-records [ records: list # List of {hostname, ip_address, record_type, zone, ttl, comment} --check ] -> record { log info $"Batch adding ($records | length) DNS records via API" if $check { log info "Check mode: Would batch add DNS records via API" return { total: ($records | length) added: ($records | length) failed: 0 check_mode: true } } let body = { records: $records } let result = call-dns-api "/records/batch" "POST" $body if $result.success { log info "DNS records batch added via API" $result.response } else { log error $"Failed to batch add DNS records via API: ($result.error)" { total: ($records | length) added: 0 failed: ($records | length) error: $result.error } } } # Batch remove DNS records via API export def api-batch-remove-records [ hostnames: list # List of hostnames --zone: string = "provisioning.local" --check ] -> record { log info $"Batch removing ($hostnames | length) DNS records via API" if $check { log info "Check mode: Would batch remove DNS records via API" return { total: ($hostnames | length) removed: ($hostnames | length) failed: 0 check_mode: true } } let body = { zone: $zone hostnames: $hostnames } let result = call-dns-api "/records/batch" "DELETE" $body if $result.success { log info "DNS records batch removed via API" $result.response } else { log error $"Failed to batch remove DNS records via API: ($result.error)" { total: ($hostnames | length) removed: 0 failed: ($hostnames | length) error: $result.error } } } # Query DNS via API export def api-query-dns [ hostname: string # Hostname to query --type: string = "A" # Record type --zone: string = "provisioning.local" ] -> record { log debug $"Querying DNS via API: ($hostname) ($type)" let result = call-dns-api $"/query?hostname=($hostname)&type=($type)&zone=($zone)" "GET" if $result.success { $result.response } else { log error $"Failed to query DNS via API: ($result.error)" { hostname: $hostname type: $type found: false error: $result.error } } } # Export zone file via API export def api-export-zone [ zone: string # Zone name --output: string = "" # Output file path (optional) ] -> string { log debug $"Exporting zone via API: ($zone)" let result = call-dns-api $"/zones/($zone)/export" "GET" if $result.success { let zone_content = $result.response.content if ($output | is-not-empty) { $zone_content | save -f $output log info $"Zone exported to ($output)" } $zone_content } else { log error $"Failed to export zone via API: ($result.error)" "" } } # Import zone file via API export def api-import-zone [ zone: string # Zone name zone_file: string # Path to zone file --check ] -> bool { log info $"Importing zone via API: ($zone)" if $check { log info "Check mode: Would import zone via API" return true } if not ($zone_file | path exists) { log error $"Zone file not found: ($zone_file)" return false } let zone_content = open $zone_file let body = { zone: $zone content: $zone_content } let result = call-dns-api "/zones/import" "POST" $body if $result.success { log info $"Zone imported via API: ($zone)" true } else { log error $"Failed to import zone via API: ($result.error)" false } } # Get DNS statistics via API export def api-get-stats [] -> record { log debug "Getting DNS statistics via API" let result = call-dns-api "/stats" "GET" if $result.success { $result.response } else { log error $"Failed to get DNS statistics via API: ($result.error)" {} } } # Validate zone via API export def api-validate-zone [ zone: string # Zone name ] -> record { log debug $"Validating zone via API: ($zone)" let result = call-dns-api $"/zones/($zone)/validate" "GET" if $result.success { $result.response } else { log error $"Failed to validate zone via API: ($result.error)" { valid: false error: $result.error } } }