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