Source code for dns_sprockets_lib.dns_sprockets_impl

'''
dns_sprockets_impl - DNS Zone validation tool implementation class.

.. Copyright (c) 2015 Neustar, Inc. All rights reserved.
.. See COPYRIGHT.txt for full notice.  See LICENSE.txt for terms and conditions.
'''


import time

import dns_sprockets_lib.loader_classes as loader_classes
import dns_sprockets_lib.validators as validators
import dns_sprockets_lib.validator_classes as validator_classes


[docs]class DNSSprocketsImpl(object): # pylint: disable=too-few-public-methods ''' Performs zone validation. '''
[docs] def __init__(self, avail_loaders, avail_tests, args): ''' Constructor. @param avail_loaders List of loader module names. @param avail_tests LIst of validator module names. @param args The application's command-line args. ''' self.avail_loaders = avail_loaders self.avail_tests = avail_tests self.args = args
[docs] def run(self): ''' Runs the instance, which loads a zone with the specified loader, and loads and runs the specified tests. @return (loader_elapsed_time, test_count, error_count) ''' # Create the zone loader instance: loader_classes.load_all() loader_class = loader_classes.ALL_CLASSES[self.args.loader] loader = loader_class(self.args) # Create the test instances: validator_classes.load_all() tests_pool = self.args.include_tests or self.avail_tests test_names = [t for t in tests_pool if t not in self.args.exclude_tests] tests = { validators.ZONE_TEST: [], validators.NODE_TEST: [], validators.RRSET_TEST: [], validators.REC_TEST: []} for test_name in test_names: test_class = validator_classes.ALL_CLASSES[test_name] test = test_class(self.args) tests[test.TEST_TYPE].append(test) # Load the zone: load_start_time = time.time() zone_obj = loader.run() load_time = time.time() - load_start_time if not zone_obj: raise RuntimeError('No zone to validate!') context = validators.Context(self.args, zone_obj) # Print some stats: print '# Checking zone:', context.zone_name print '# Loader: %s from: %s elapsed=%f secs' % ( self.args.loader, self.args.source, load_time) if self.args.force_dnssec_type == 'detect': print '# Zone appears to be DNSSEC type:', context.dnssec_type else: print '# Forcing DNSSEC type for zone to:', context.dnssec_type print '# Extra defines:', self.args.defines # Filter tests based on zone's DNSSEC type: running_test_names = [] for tests_type in tests.keys(): validators.dnssec_filter_tests_by_context(tests[tests_type], context) running_test_names += [test.TEST_NAME for test in tests[tests_type]] print '# Running tests:', running_test_names counts = {'tests': 0, 'errors': 0} # Run the zone tests: for test in tests[validators.ZONE_TEST]: DNSSprocketsImpl._run_test(self.args, test, context, counts) # Run the node, rrset, and rec tests: for name in context.node_names: node = context.zone_obj.get_node(name) if node: # Not present for Empty Non-Terminals # Node tests: for test in tests[validators.NODE_TEST]: test_node = validators.filter_node(node, test.TEST_RRTYPE) DNSSprocketsImpl._run_test( self.args, test, context, counts, name=name, node=test_node) # RRSet tests: for rdataset in node.rdatasets: for test in tests[validators.RRSET_TEST]: if validators.test_covers_type(test, rdataset.rdtype): DNSSprocketsImpl._run_test( self.args, test, context, counts, name=name, rdataset=rdataset) # Rec tests: for rdata in rdataset: for test in tests[validators.REC_TEST]: if validators.test_covers_type(test, rdata.rdtype): DNSSprocketsImpl._run_test( self.args, test, context, counts, name=name, ttl=rdataset.ttl, rdata=rdata) print '# END RESULT: %d ERRORS in %d tests' % (counts['errors'], counts['tests']) return (load_time, counts['tests'], counts['errors'])
@staticmethod def _run_test(args, test, context, counts, **kwargs): ''' Runs an individual test. @param args The application's command-line args. @param test The validator instance to use. @param context The testing context. @param counts Dictionary of test and error counts. @param kwargs Other parameters specific to the TEST_TYPE being run. ''' suggested_tested = validators.make_suggested_tested(test, context, **kwargs) (tested, result) = test.run(context, suggested_tested, **kwargs) if tested is not None: counts['tests'] += 1 good = not result if not good: counts['errors'] += 1 if not good or not args.errors_only: print 'TEST %s(%s) => %s' % ( test.TEST_NAME, tested, good and 'OK' or 'FAIL: %s' % (result)) # end of file