From 5cc37a15a5a5d1b4950c79b2298806dbadde4643 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sun, 22 Dec 2019 03:07:59 +0000 Subject: feat(defzone): Add plist argument format for SOA records These records have so many fields that it's difficult to track what's what in a long list. For convenience they're now specified in plist format (see the example). There isn't really a point to this because the SOA record is the one I care the *least* about practically as Cloud DNS sets it for me, but whatever. --- tools/emacs-pkgs/defzone/defzone.el | 76 +++++++++++++++++++++---------------- tools/emacs-pkgs/defzone/example.el | 10 ++++- 2 files changed, 52 insertions(+), 34 deletions(-) diff --git a/tools/emacs-pkgs/defzone/defzone.el b/tools/emacs-pkgs/defzone/defzone.el index b67501cbd860..ffd359e5ff83 100644 --- a/tools/emacs-pkgs/defzone/defzone.el +++ b/tools/emacs-pkgs/defzone/defzone.el @@ -8,38 +8,50 @@ "Evaluate a record definition and turn it into a zone file record in ZONE, optionally prefixed with SUBDOMAIN." - (declare (indent defun)) ; TODO(tazjin): remove - (let ((name (if subdomain (s-join "." (list subdomain zone)) zone))) - (pcase record - (`(SOA . (,ttl . (,mname ,rname ,serial ,refresh ,retry ,expire ,min))) - (format "%s %s IN SOA %s %s %s %s %s %s %s" - name ttl mname rname serial refresh retry expire min)) - - (`(NS . (,ttl . ,targets)) - (->> targets - (-map (lambda (target) (format "%s %s IN NS %s" name ttl target))) - (s-join "\n"))) - - (`(MX . (,ttl . ,pairs)) - (->> pairs - (-map (-lambda ((preference . exchange)) - (format "%s %s IN MX %s %s" name ttl preference exchange))) - (s-join "\n"))) - - (`(TXT ,ttl ,text) (format "%s %s IN TXT %s" name ttl (prin1-to-string text))) - - (`(A . (,ttl . ,ips)) - (->> ips - (-map (lambda (ip) (format "%s %s IN A %s" name ttl ip))) - (s-join "\n"))) - - (`(CNAME ,ttl ,target) (format "%s %s IN CNAME %s" name ttl target)) - - ((and `(,sub . ,records) - (guard (stringp sub))) - (s-join "\n" (-map (lambda (r) (record-to-record zone r sub)) records))) - - (_ (error "Invalid record definition: %s" record))))) + (cl-labels ((plist->alist (plist) + (when plist + (cons + (cons (car plist) (cadr plist)) + (plist->alist (cddr plist)))))) + (let ((name (if subdomain (s-join "." (list subdomain zone)) zone))) + (pcase record + ;; SOA RDATA (RFC 1035; 3.3.13) + ((and `(SOA . (,ttl . ,keys)) + (let (map (:mname mname) (:rname rname) (:serial serial) + (:refresh refresh) (:retry retry) (:expire expire) + (:minimum min)) + (plist->alist keys))) + (if-let ((missing (-filter #'null (not (list mname rname serial + refresh retry expire min))))) + (error "Missing fields in SOA record: %s" missing) + (format "%s %s IN SOA %s %s %s %s %s %s %s" + name ttl mname rname serial refresh retry expire min))) + + (`(NS . (,ttl . ,targets)) + (->> targets + (-map (lambda (target) (format "%s %s IN NS %s" name ttl target))) + (s-join "\n"))) + + (`(MX . (,ttl . ,pairs)) + (->> pairs + (-map (-lambda ((preference . exchange)) + (format "%s %s IN MX %s %s" name ttl preference exchange))) + (s-join "\n"))) + + (`(TXT ,ttl ,text) (format "%s %s IN TXT %s" name ttl (prin1-to-string text))) + + (`(A . (,ttl . ,ips)) + (->> ips + (-map (lambda (ip) (format "%s %s IN A %s" name ttl ip))) + (s-join "\n"))) + + (`(CNAME ,ttl ,target) (format "%s %s IN CNAME %s" name ttl target)) + + ((and `(,sub . ,records) + (guard (stringp sub))) + (s-join "\n" (-map (lambda (r) (record-to-record zone r sub)) records))) + + (_ (error "Invalid record definition: %s" record)))))) (defmacro defzone (fqdn &rest records) "Generate zone file for the zone at FQDN from a simple DSL." diff --git a/tools/emacs-pkgs/defzone/example.el b/tools/emacs-pkgs/defzone/example.el index 6405eaf2f72c..e9c86d25eec8 100644 --- a/tools/emacs-pkgs/defzone/example.el +++ b/tools/emacs-pkgs/defzone/example.el @@ -1,8 +1,14 @@ ;;; example.el - usage example for defzone macro (defzone "tazj.in." - (SOA 21600 "ns-cloud-a1.googledomains.com." "cloud-dns-hostmaster.google.com." - 123 21600 3600 1209600 300) + (SOA 21600 + :mname "ns-cloud-a1.googledomains.com." + :rname "cloud-dns-hostmaster.google.com." + :serial 123 + :refresh 21600 + :retry 3600 + :expire 1209600 + :minimum 300) (NS 21600 "ns-cloud-a1.googledomains.com." -- cgit 1.4.1