Skip to content
Browse files

revamped some stuff

  • Loading branch information...
1 parent 755d013 commit 29ad935a4e270211c1c0eab57b5ead9f56ab54ed @uberj committed
Showing with 193 additions and 42 deletions.
  1. +4 −0 README.md
  2. +0 −4 diff.config-dist
  3. +148 −30 diffdns.py
  4. +10 −0 lib/paths.py
  5. +8 −8 lib/validate.py
  6. +23 −0 validate_view.sh-template
View
4 README.md
@@ -24,3 +24,7 @@ If you just want to test one zone use this form.
```
python diffdns.py --ns1 dev1.foo.com --ns2 ns1.foo.com --zone-name dc1.foo.com --file ~/path/to/zone/file
```
+
+```
+python diffdns.py --ns1 ns1.mozilla.com --ns2 ns2.mozilla.com --named-path ~/var/named/ --view-file ~/var/named/config/view.public --second-named-path ~/testing/var/named/ --second-view-file ~/testing/var/named/config/view.public
+```
View
4 diff.config-dist
@@ -1,4 +0,0 @@
-[zonefiles]
-# The diff script will cd into this directory to make sure and $INCLUDES
-# are done with the right path context.
-dir_path=
View
178 diffdns.py
@@ -1,36 +1,113 @@
+import os
+import sys
+import re
+
from dns import zone
from iscpy.iscpy_dns.named_importer_lib import MakeNamedDict
import argparse
from lib.validate import diff_nameservers
-
-import pdb
-import os
-import sys
-import ConfigParser
-from gettext import gettext as _, ngettext
+from lib.paths import swap_paths
# Add zones that should not be diffed here
-black_list = (,)
-
+black_list = ['weave.mozilla.com', 'discovershiretoko.org']
-def diff_zones(ns1, ns2, zone_file):
- config = ConfigParser.ConfigParser()
- config.read("diff.config")
- ZONE_PATH = config.get('zonefiles','dir_path')
+def diff_zones(ns1, ns2, zone_file, named_path):
zones = MakeNamedDict(open(zone_file).read())
for zone_name, zone_meta in zones['orphan_zones'].iteritems():
+ if zone_meta['type'] != 'master':
+ continue
if zone_name in black_list:
continue
- handle_zone([ns1, ns2], zone_name, zone_meta, ZONE_PATH)
+ handle_zone([ns1, ns2], zone_name, zone_meta, named_path)
-def diff_zone(ns1, ns2, zone_name, zone_file):
- config = ConfigParser.ConfigParser()
- config.read("diff.config")
- ZONE_PATH = config.get('zonefiles','dir_path')
- handle_zone([ns1, ns2], zone_name, {'file': zone_file}, ZONE_PATH)
+
+def diff_zone(ns1, ns2, zone_name, zone_file, named_path):
+ handle_zone([ns1, ns2], zone_name, {'file': zone_file}, named_path)
+
+
+def diff_view(ns1, ns2, view_file1, named_path1, named_path2=None,
+ view_file2=None):
+ if view_file2 and named_path2:
+ if diff_view_contents(named_path1, named_path2, view_file1,
+ view_file2):
+ print "-- Found differences, not continuing"
+ return
+ zones = parse_view_config_data(named_path1, view_file1)
+ print "Using files under {0} as the datasource.".format(named_path1)
+ for zone_name, zone_meta in zones.iteritems():
+ if zone_meta['type'] != 'master':
+ continue
+ if zone_name in black_list:
+ continue
+ handle_zone([ns1, ns2], zone_name, zone_meta, named_path1)
+
+
+def diff_view_contents(named_path1, named_path2, view_file1, view_file2):
+ zones1 = set(parse_view_config_data(named_path1, view_file1))
+ zones2 = set(parse_view_config_data(named_path2, view_file2))
+
+ ldiff = zones1 - zones2
+ rdiff = zones2 - zones1
+
+ difference = False
+
+ if ldiff:
+ difference = True
+ msg = "zones statments that were in {0} but not in {1}:".format(
+ view_file1, view_file2
+ )
+ print '=' * len(msg)
+ print msg
+ print '=' * len(msg)
+ for lz in ldiff:
+ print lz
+
+ if rdiff:
+ difference = True
+ msg = "zones statments that were in {0} but not in {1}:".format(
+ view_file2, view_file1
+ )
+ print '=' * len(msg)
+ print msg
+ print '=' * len(msg)
+ for rz in rdiff:
+ print rz
+
+ return difference
+
+
+def parse_view_config_data(named_path, view_file):
+ include_m = re.compile("\s+include\s+['\"](\S+)['\"]")
+ includes = []
+ with open(view_file) as fd:
+ for line in fd:
+ m = include_m.match(line)
+ if m:
+ path = m.groups()[0]
+ includes.append(swap_fpaths(path))
+
+ zones = {}
+ for conf_file in includes:
+ parsed = parse_config_data(named_path, conf_file)
+ zones.update(parsed)
+ return zones
+
+
+def swap_fpaths(path):
+ for s in swap_paths:
+ path = path.replace(*s)
+ return path
+
+
+def parse_config_data(named_path, filepath):
+ cwd = os.getcwd()
+ os.chdir(named_path)
+ zones = MakeNamedDict(open(filepath).read())
+ os.chdir(cwd)
+ return zones['orphan_zones']
def get_zone_data(zone_name, filepath, dirpath):
@@ -61,22 +138,63 @@ def handle_zone(nss, zone_name, zone_meta, ZONE_PATH):
parser.add_argument('--file', dest="data_file", help="A single zone file."
" Use this option with the --zone option", type=str)
+ parser.add_argument(
+ '--named-path', dest='named_path1', type=str, required=True,
+ help="A full path to where named would be running."
+ )
+
+ parser.add_argument(
+ '--second-named-path', dest='named_path2', type=str, default=None,
+ help="Used to help resolve file paths when --second-view-file is used."
+ )
+
group = parser.add_mutually_exclusive_group(required=True)
- group.add_argument('--zones-file', help="A file containing bind zone "
- "statements.")
- group.add_argument('--zone-name', help="A single zone's name. Use the "
- "--file option to specify where to find it's zone "
- "file.")
+ group.add_argument(
+ '--zones-file', help="A file containing bind zone statements."
+ )
+
+ group.add_argument(
+ '--zone-name', help="A single zone's name. Use the "
+ "--file option to specify where to find it's zone "
+ "file."
+ )
+ group.add_argument(
+ '--view-file', dest='view_file1', type=str,
+ default=None, help="A full file path to a view file"
+ )
+
+ parser.add_argument(
+ '--second-view-file', dest='view_file2', type=str,
+ default=None, help="An optional file. If both view-file and "
+ "second-view-file are provided, their contents will be compared "
+ "statically"
+ )
nas = parser.parse_args(sys.argv[1:])
- print nas
if nas.zone_name and not nas.data_file:
- print _("When using the --zone-name option you must specify the "
- "zone's file with --file")
-
- if nas.zones_file:
- diff_zones(nas.ns1, nas.ns2, nas.zones_file)
+ print ("When using the --zone-name option you must specify the "
+ "zone's file with --file")
+ sys.exit(1)
+
+ if nas.view_file2 and not nas.view_file1:
+ print "Speciefy view-file when using second-view-file"
+ sys.exit(1)
+
+ if nas.view_file2 and not nas.named_path2:
+ print "Speciefy second-named-path when using second-view-file"
+ sys.exit(1)
+
+ if nas.view_file1:
+ diff_view(
+ nas.ns1, nas.ns2, nas.view_file1, nas.named_path1,
+ named_path2=nas.named_path2, view_file2=nas.view_file2
+ )
+ elif nas.zones_file:
+ diff_zones(nas.ns1, nas.ns2, nas.zones_file, nas.named_path1)
elif nas.zone_name:
- diff_zone(nas.ns1, nas.ns2, nas.zone_name, nas.data_file)
+ diff_zone(
+ nas.ns1, nas.ns2, nas.zone_name, nas.data_file, nas.named_path1
+ )
+ print "Done diffing!"
View
10 lib/paths.py
@@ -0,0 +1,10 @@
+# Since this tool doesn't chroot and named does, we must be smart about file
+# paths. The tuple 'swap_paths' contains tuples that will have the left side
+# swaped with the right side.
+# I.E:
+# If swap_paths contained ('/foo/bar/', '/baz/bar'), any path encounered by the
+# script would have any occurences of '/foo/bar/' swapped with '/baz/bar/'
+swap_paths = (
+ ('/var/run/named/', ''),
+ ('/var/named/', ''),
+)
View
16 lib/validate.py
@@ -1,15 +1,14 @@
import subprocess
-import sys
import os
-import pdb
import itertools
from dns import zone
-from dns.zone import NoSOA
def resolve(name, ns, rdclass="all"):
- proc = subprocess.Popen(["dig", "@{0}".format(ns), name, rdclass,
- "+short"], stdout=subprocess.PIPE)
+ proc = subprocess.Popen(
+ ["dig", "@{0}".format(ns), name, rdclass, "+short"],
+ stdout=subprocess.PIPE
+ )
x = proc.communicate()[0]
x = x.split('\n')
x = '\n'.join(sorted(x))
@@ -32,14 +31,15 @@ def check_rdtype(zone, nss, rdtype):
res = resolve(name, ns, rdclass=rdtype)
if res.strip('\n').find("unused") != -1:
continue
- results.append(res)
+ results.append(res.lower())
if len(set(results)) > 1: # set() removes duplicates
print "------------------------------------"
print "Found differences for {0} {1}:".format(rdtype, name)
for ns, result in itertools.izip(nss, results):
- print "{0} returned:\n-->\n{1}\n<--".format(ns,
- result.strip('\n'))
+ print "{0} returned:\n-->\n{1}\n<--".format(
+ ns, result.strip('\n')
+ )
def diff_nameservers(nss, zone_name, mzone):
View
23 validate_view.sh-template
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+if [[ ${EUID} != 0 ]] ; then
+ echo "Run this as root"
+ exit 1
+fi
+
+NS1= # Production ns
+NAMED_PATH1= # Path to active DNS data
+VIEW1= # View file
+
+NS2= # Testing ns
+NAMED_PATH2= # The one with the patch
+VIEW2= #view file
+
+
+DIFFDNS= # path to diffdns.py
+PYTHONPATH=.:PYTHONPATH
+
+/etc/init.d/named restart
+cd $BIND_DIR
+python $DIFFDNS --ns1 $NS1 --ns2 $NS2 --named-path $NAMED_PATH1 --view-file $VIEW1 --second-named-path $NAMED_PATH2 --second-view-file $VIEW2
+cd -

0 comments on commit 29ad935

Please sign in to comment.
Something went wrong with that request. Please try again.