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

501 lines
13 KiB
Text

# CoreDNS CLI Commands
# User-facing commands for DNS management
# Selective imports (ADR-025 Phase 3 Layer 2).
# ../utils/log.nu was a broken import (file does not exist) — removed.
# ../utils/logging.nu star-import was dead — dropped.
use domain/config/loader.nu [get-config]
use domain/coredns/service.nu [
check-coredns-health get-coredns-status install-coredns reload-coredns
restart-coredns show-coredns-logs start-coredns stop-coredns
]
use domain/coredns/zones.nu [
add-a-record add-aaaa-record add-cname-record add-mx-record add-txt-record
create-zone-file list-zone-records remove-record validate-zone-file
]
use domain/coredns/corefile.nu [update-corefile validate-corefile]
# DNS service status
export def "dns status" [] {
log info "Checking CoreDNS status"
let config = get-dns-config
let status = get-coredns-status --config $config
print $"
CoreDNS Service Status
======================
Status: ($status.running | if $in { 'Running ✓' } else { 'Stopped ✗' })
Deployment: ($status.deployment_type)
Mode: ($status.mode)
PID: ($status.pid | default 'N/A')
Healthy: ($status.healthy | if $in { 'Yes ✓' } else { 'No ✗' })
"
if $status.running {
let local_config = $config.local? | default {}
let port = $local_config.port? | default 5353
let zones = $local_config.zones? | default []
print $"
Configuration
-------------
Port: ($port)
Zones: ($zones | str join ', ')
"
}
}
# Start DNS service
export def "dns start" [
--foreground (-f) # Run in foreground
--check # Check mode
] {
let config = get-dns-config
let result = start-coredns $config --foreground=$foreground --check=$check
if $result {
print "✓ CoreDNS started successfully"
} else {
print "✗ Failed to start CoreDNS"
exit 1
}
}
# Stop DNS service
export def "dns stop" [
--check # Check mode
] {
let config = get-dns-config
let result = stop-coredns --config $config --check=$check
if $result {
print "✓ CoreDNS stopped successfully"
} else {
print "✗ Failed to stop CoreDNS"
exit 1
}
}
# Reload DNS configuration
export def "dns reload" [] {
let config = get-dns-config
let result = reload-coredns --config $config
if $result {
print "✓ CoreDNS reloaded successfully"
} else {
print "✗ Failed to reload CoreDNS"
exit 1
}
}
# Restart DNS service
export def "dns restart" [
--check # Check mode
] {
let config = get-dns-config
let result = restart-coredns $config --check=$check
if $result {
print "✓ CoreDNS restarted successfully"
} else {
print "✗ Failed to restart CoreDNS"
exit 1
}
}
# Install CoreDNS binary
export def "dns install" [
version?: string = "latest" # Version to install
--check
] {
let result = install-coredns $version --check=$check
if $result {
print $"✓ CoreDNS ($version) installed successfully"
} else {
print "✗ Failed to install CoreDNS"
exit 1
}
}
# Show DNS logs
export def "dns logs" [
--lines: int = 50 # Number of lines to show
--follow (-f) # Follow log output
] {
show-coredns-logs --lines $lines --follow=$follow
}
# Zone management commands
# List DNS zones
export def "dns zone list" [] {
let config = get-dns-config
let local_config = $config.local? | default {}
let zones = $local_config.zones? | default []
let zones_path = $local_config.zones_path? | default "~/.provisioning/coredns/zones" | path expand
print $"
DNS Zones
=========
"
for zone in $zones {
let zone_file = $"($zones_path)/($zone).zone"
let exists = $zone_file | path exists
print $" • ($zone) ($exists | if $in { '✓' } else { '✗ (missing)' })"
}
}
# Show zone details
export def "dns zone show" [
zone: string # Zone name
--format: string = "table" # Output format: table, json, yaml
] {
let records = list-zone-records $zone --format $format
if $format == "table" {
print $"\nZone: ($zone)\n"
$records | table
} else {
print $records
}
}
# Create DNS zone
export def "dns zone create" [
zone: string # Zone name
--check
] {
if $check {
print $"Check mode: Would create zone ($zone)"
return
}
let config = get-dns-config
let local_config = $config.local? | default {}
let zones_path = $local_config.zones_path? | default "~/.provisioning/coredns/zones"
let result = create-zone-file $zone $zones_path --config $config
if $result {
print $"✓ Zone ($zone) created successfully"
# Update Corefile
dns config generate
} else {
print $"✗ Failed to create zone ($zone)"
exit 1
}
}
# Delete DNS zone
export def "dns zone delete" [
zone: string # Zone name
--force # Skip confirmation
--check
] {
if not $force {
let confirm = input $"Are you sure you want to delete zone ($zone)? (yes/no): "
if $confirm != "yes" {
print "Cancelled"
return
}
}
if $check {
print $"Check mode: Would delete zone ($zone)"
return
}
let config = get-dns-config
let local_config = $config.local? | default {}
let zones_path = $local_config.zones_path? | default "~/.provisioning/coredns/zones" | path expand
let zone_file = $"($zones_path)/($zone).zone"
if ($zone_file | path exists) {
rm $zone_file
print $"✓ Zone ($zone) deleted successfully"
} else {
print $"✗ Zone ($zone) not found"
exit 1
}
}
# Record management commands
# Add DNS record
export def "dns record add" [
name: string # Record name
type: string # Record type (A, AAAA, CNAME, MX, TXT, etc.)
value: string # Record value
--zone: string = "provisioning.local" # Zone name
--ttl: int = 300 # TTL in seconds
--priority: int # Priority (for MX/SRV)
--comment: string = "" # Comment
--check
] {
if $check {
print $"Check mode: Would add record ($name) ($type) ($value) to zone ($zone)"
return
}
let result = match $type {
"A" => { add-a-record $zone $name $value --ttl $ttl --comment $comment }
"AAAA" => { add-aaaa-record $zone $name $value --ttl $ttl --comment $comment }
"CNAME" => { add-cname-record $zone $name $value --ttl $ttl --comment $comment }
"MX" => {
if $priority == null {
print "Error: --priority required for MX records"
exit 1
}
add-mx-record $zone $name $value $priority --ttl $ttl --comment $comment
}
"TXT" => { add-txt-record $zone $name $value --ttl $ttl --comment $comment }
_ => {
print $"Error: Unsupported record type ($type)"
exit 1
}
}
if $result {
print $"✓ Record added: ($name) ($type) ($value)"
# Reload CoreDNS
reload-coredns --config (get-dns-config)
} else {
print $"✗ Failed to add record"
exit 1
}
}
# Remove DNS record
export def "dns record remove" [
name: string # Record name
--zone: string = "provisioning.local" # Zone name
--check
] {
if $check {
print $"Check mode: Would remove record ($name) from zone ($zone)"
return
}
let result = remove-record $zone $name
if $result {
print $"✓ Record removed: ($name)"
# Reload CoreDNS
reload-coredns --config (get-dns-config)
} else {
print $"✗ Failed to remove record"
exit 1
}
}
# List DNS records
export def "dns record list" [
--zone: string = "provisioning.local" # Zone name
--format: string = "table" # Output format
] {
let records = list-zone-records $zone --format $format
if $format == "table" {
print $"\nDNS Records - Zone: ($zone)\n"
$records | table
} else {
print $records
}
}
# Update DNS record
export def "dns record update" [
name: string # Record name
type: string # Record type
value: string # New value
--zone: string = "provisioning.local" # Zone name
--ttl: int = 300 # TTL
--comment: string = "" # Comment
--check
] {
if $check {
print $"Check mode: Would update record ($name) to ($value) in zone ($zone)"
return
}
# Remove old record
let remove_result = remove-record $zone $name
if not $remove_result {
print $"✗ Failed to remove old record"
exit 1
}
# Add new record
dns record add $name $type $value --zone $zone --ttl $ttl --comment $comment
}
# Query DNS
export def "dns query" [
hostname: string # Hostname to query
--type: string = "A" # Record type
--server: string = "127.0.0.1" # DNS server
--port: int = 5353 # DNS port
] {
log info $"Querying ($hostname) ($type) from ($server):($port)"
let result = (do {
dig @$server -p $port $hostname $type
} | complete)
if $result.exit_code != 0 {
print "✗ DNS query failed"
exit 1
}
}
# Configuration commands
# Show DNS configuration
export def "dns config show" [] {
let config = get-dns-config
print $"
CoreDNS Configuration
=====================
"
print ($config | to yaml)
}
# Validate DNS configuration
export def "dns config validate" [] {
let config = get-dns-config
let local_config = $config.local? | default {}
let config_path = $local_config.config_path? | default "~/.provisioning/coredns/Corefile" | path expand
# Validate Corefile
let corefile_validation = validate-corefile $config_path
print $"
Corefile Validation
===================
Valid: ($corefile_validation.valid | if $in { 'Yes ✓' } else { 'No ✗' })
"
if not ($corefile_validation.errors | is-empty) {
print "Errors:"
for error in $corefile_validation.errors {
print $" • ($error)"
}
}
if not ($corefile_validation.warnings | is-empty) {
print "\nWarnings:"
for warning in $corefile_validation.warnings {
print $" • ($warning)"
}
}
# Validate zone files
let zones = $local_config.zones? | default []
print $"\n\nZone Files Validation\n=====================\n"
for zone in $zones {
let zone_validation = validate-zone-file $zone
print $"Zone: ($zone)"
print $" Valid: ($zone_validation.valid | if $in { 'Yes ✓' } else { 'No ✗' })"
if not ($zone_validation.errors | is-empty) {
print " Errors:"
for error in $zone_validation.errors {
print $" • ($error)"
}
}
if not ($zone_validation.warnings | is-empty) {
print " Warnings:"
for warning in $zone_validation.warnings {
print $" • ($warning)"
}
}
print ""
}
}
# Generate DNS configuration
export def "dns config generate" [
--check
] {
if $check {
print "Check mode: Would generate DNS configuration"
return
}
let config = get-dns-config
let local_config = $config.local? | default {}
let config_path = $local_config.config_path? | default "~/.provisioning/coredns/Corefile" | path expand
let result = update-corefile $config $config_path
if $result {
print $"✓ Corefile generated at ($config_path)"
} else {
print "✗ Failed to generate Corefile"
exit 1
}
}
# Health check
export def "dns health" [] {
let config = get-dns-config
let health = check-coredns-health $config
if $health {
print "✓ CoreDNS is healthy"
} else {
print "✗ CoreDNS health check failed"
exit 1
}
}
# Helper: Get DNS configuration
def get-dns-config [] -> record {
let full_config = get-config
# Try to get CoreDNS config from configuration
let coredns_config = $full_config.coredns? | default {
mode: "local"
local: {
enabled: true
deployment_type: "binary"
binary_path: "~/.provisioning/bin/coredns"
config_path: "~/.provisioning/coredns/Corefile"
zones_path: "~/.provisioning/coredns/zones"
port: 5353
auto_start: true
zones: ["provisioning.local", "workspace.local"]
}
dynamic_updates: {
enabled: true
api_endpoint: "http://localhost:8080/dns"
auto_register_servers: true
}
upstream: ["8.8.8.8", "1.1.1.1"]
default_ttl: 300
enable_logging: true
enable_metrics: true
metrics_port: 9153
}
$coredns_config
}