about summary refs log tree commit diff
path: root/tools/emacs-pkgs/defzone/defzone.el
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@google.com>2019-12-22T03·07+0000
committerVincent Ambo <tazjin@google.com>2020-04-20T21·39+0100
commit5cc37a15a5a5d1b4950c79b2298806dbadde4643 (patch)
tree8e0faabe0ae3e71e0590988dbf087416276b60a9 /tools/emacs-pkgs/defzone/defzone.el
parent8c86b9b5f60af4d2bd16352ace7b19fdde04ffda (diff)
feat(defzone): Add plist argument format for SOA records r/642
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.
Diffstat (limited to 'tools/emacs-pkgs/defzone/defzone.el')
-rw-r--r--tools/emacs-pkgs/defzone/defzone.el76
1 files changed, 44 insertions, 32 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."