1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
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}
|