feat(defzone): Add an Emacs package for generating zone files
This currently only supports a small subset of available records, but I actually kind of like the nesting.
This commit is contained in:
parent
d6f5ca7caf
commit
8c86b9b5f6
2 changed files with 87 additions and 0 deletions
48
tools/emacs-pkgs/defzone/defzone.el
Normal file
48
tools/emacs-pkgs/defzone/defzone.el
Normal file
|
@ -0,0 +1,48 @@
|
|||
;;; defzone.el --- Generate zone files from Elisp -*- lexical-binding: t; -*-
|
||||
|
||||
(require 'dash)
|
||||
(require 'dash-functional)
|
||||
(require 's)
|
||||
|
||||
(defun record-to-record (zone record &optional subdomain)
|
||||
"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)))))
|
||||
|
||||
(defmacro defzone (fqdn &rest records)
|
||||
"Generate zone file for the zone at FQDN from a simple DSL."
|
||||
(declare (indent defun))
|
||||
|
||||
`(s-join "\n" (-map (lambda (r) (record-to-record ,fqdn r)) (quote ,records))))
|
39
tools/emacs-pkgs/defzone/example.el
Normal file
39
tools/emacs-pkgs/defzone/example.el
Normal file
|
@ -0,0 +1,39 @@
|
|||
;;; 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)
|
||||
|
||||
(NS 21600
|
||||
"ns-cloud-a1.googledomains.com."
|
||||
"ns-cloud-a2.googledomains.com."
|
||||
"ns-cloud-a3.googledomains.com."
|
||||
"ns-cloud-a4.googledomains.com.")
|
||||
|
||||
(MX 300
|
||||
(1 . "aspmx.l.google.com.")
|
||||
(5 . "alt1.aspmx.l.google.com.")
|
||||
(5 . "alt2.aspmx.l.google.com.")
|
||||
(10 . "alt3.aspmx.l.google.com.")
|
||||
(10 . "alt4.aspmx.l.google.com."))
|
||||
|
||||
(TXT 3600 "google-site-verification=d3_MI1OwD6q2OT42Vvh0I9w2u3Q5KFBu-PieNUE1Fig")
|
||||
|
||||
(A 300 "34.98.120.189")
|
||||
|
||||
;; Nested record sets are indicated by a list that starts with a
|
||||
;; string (this is just joined, so you can nest multiple levels at
|
||||
;; once)
|
||||
("blog"
|
||||
;; Blog "storage engine" is in a separate DNS zone
|
||||
(NS 21600
|
||||
"ns-cloud-c1.googledomains.com."
|
||||
"ns-cloud-c2.googledomains.com."
|
||||
"ns-cloud-c3.googledomains.com."
|
||||
"ns-cloud-c4.googledomains.com."))
|
||||
|
||||
("git"
|
||||
(A 300 "34.98.120.189")
|
||||
(TXT 300 "<3 edef"))
|
||||
|
||||
("files" (CNAME 300 "c.storage.googleapis.com.")))
|
Loading…
Reference in a new issue