provisioning-core/nulib/domain/coredns/api_client.nu

428 lines
11 KiB
Text
Raw Normal View History

# 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<string> # 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
}
}
}