501 lines
13 KiB
Text
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
|
|
}
|