aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron LI <aly@aaronly.me>2018-02-28 13:05:52 +0800
committerAaron LI <aly@aaronly.me>2018-03-14 11:28:44 +0800
commit67fa5be1b042fd6ace7e140939f58ea3680efd8c (patch)
tree8a69b4375086efbca40ced86d3f9bbe5fec867e5
parent2d8ca670d9148c7de2a95c8448985f74238d7cdb (diff)
downloadansible-dfly-vps-67fa5be1b042fd6ace7e140939f58ea3680efd8c.tar.bz2
Add filter_plugins/dns.py with "next_serial" to DNS SOA record
Credit: https://github.com/kgaughan/zones
-rw-r--r--filter_plugins/dns.py74
1 files changed, 74 insertions, 0 deletions
diff --git a/filter_plugins/dns.py b/filter_plugins/dns.py
new file mode 100644
index 0000000..9fdca29
--- /dev/null
+++ b/filter_plugins/dns.py
@@ -0,0 +1,74 @@
+# Credit: https://github.com/kgaughan/zones
+
+"""
+Custom Ansible template filters for DNS management.
+"""
+
+import os
+import datetime
+import random
+import shlex
+import subprocess
+
+
+def which(cmd):
+ for path in os.environ["PATH"].split(os.pathsep):
+ full_path = os.path.join(path, cmd)
+ if os.access(full_path, os.X_OK):
+ return full_path
+ return None
+
+
+def run_query(cmd, rtype, fqdn, ns=None):
+ if not fqdn.endswith("."):
+ fqdn += "."
+ args = [cmd, fqdn, rtype]
+ if ns:
+ args.append("@" + ns)
+
+ output = subprocess.check_output(args, universal_newlines=True)
+ for line in output.split("\n"):
+ if line.startswith(";"):
+ continue
+ parsed = shlex.split(line)
+ if len(parsed) > 0 and parsed[0] == fqdn and parsed[3] == rtype:
+ yield parsed[4:]
+
+
+def next_serial(fqdn):
+ cmd = "drill"
+ cmd_path = which(cmd)
+ if cmd_path is None:
+ raise Exception("Cannot find %s" % cmd)
+
+ def query_nameservers(fqdn, ns=None):
+ return [line[0] for line in run_query(cmd_path, "NS", fqdn, ns)]
+
+ # Get a registry nameserver.
+ reg_ns = random.choice(query_nameservers(".".join(fqdn.split(".")[1:])))
+
+ nss = query_nameservers(fqdn, reg_ns)
+ random.shuffle(nss)
+
+ current_serial = None
+ for ns in nss:
+ try:
+ for line in run_query(cmd_path, "SOA", fqdn, ns):
+ current_serial = line[2]
+ break
+ except subprocess.CalledProcessError as e:
+ if e.returncode not in [9]:
+ raise
+ if current_serial is not None:
+ break
+
+ today = datetime.datetime.utcnow().strftime("%Y%m%d")
+ if current_serial is None or current_serial[:8] != today:
+ return today + "00"
+ else:
+ return str(int(current_serial) + 1)
+
+
+class FilterModule(object):
+ def filters(self):
+ return {"next_serial": next_serial}